/*
 * Copyright 2013 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.
 */

// This file is automatically generated

(function (global) {
  if (global.DataView)
    return;
  if (!global.ArrayBuffer)
    fail('ArrayBuffer not supported');
  if (!Object.defineProperties)
    fail('This module requires ECMAScript 5');
  var nativele = new Int8Array(new Int32Array([
      1
    ]).buffer)[0] === 1;
  var temp = new Uint8Array(8);
  global.DataView = function DataView(buffer, offset, length) {
    if (!(buffer instanceof ArrayBuffer))
      fail('Bad ArrayBuffer');
    offset = offset || 0;
    length = length || buffer.byteLength - offset;
    if (offset < 0 || length < 0 || offset + length > buffer.byteLength)
      fail('Illegal offset and/or length');
    Object.defineProperties(this, {
      buffer: {
        value: buffer,
        enumerable: false,
        writable: false,
        configurable: false
      },
      byteOffset: {
        value: offset,
        enumerable: false,
        writable: false,
        configurable: false
      },
      byteLength: {
        value: length,
        enumerable: false,
        writable: false,
        configurable: false
      },
      _bytes: {
        value: new Uint8Array(buffer, offset, length),
        enumerable: false,
        writable: false,
        configurable: false
      }
    });
  };
  global.DataView.prototype = {
    constructor: DataView,
    getInt8: function getInt8(offset) {
      return get(this, Int8Array, 1, offset);
    },
    getUint8: function getUint8(offset) {
      return get(this, Uint8Array, 1, offset);
    },
    getInt16: function getInt16(offset, le) {
      return get(this, Int16Array, 2, offset, le);
    },
    getUint16: function getUint16(offset, le) {
      return get(this, Uint16Array, 2, offset, le);
    },
    getInt32: function getInt32(offset, le) {
      return get(this, Int32Array, 4, offset, le);
    },
    getUint32: function getUint32(offset, le) {
      return get(this, Uint32Array, 4, offset, le);
    },
    getFloat32: function getFloat32(offset, le) {
      return get(this, Float32Array, 4, offset, le);
    },
    getFloat64: function getFloat32(offset, le) {
      return get(this, Float64Array, 8, offset, le);
    },
    setInt8: function setInt8(offset, value) {
      set(this, Int8Array, 1, offset, value);
    },
    setUint8: function setUint8(offset, value) {
      set(this, Uint8Array, 1, offset, value);
    },
    setInt16: function setInt16(offset, value, le) {
      set(this, Int16Array, 2, offset, value, le);
    },
    setUint16: function setUint16(offset, value, le) {
      set(this, Uint16Array, 2, offset, value, le);
    },
    setInt32: function setInt32(offset, value, le) {
      set(this, Int32Array, 4, offset, value, le);
    },
    setUint32: function setUint32(offset, value, le) {
      set(this, Uint32Array, 4, offset, value, le);
    },
    setFloat32: function setFloat32(offset, value, le) {
      set(this, Float32Array, 4, offset, value, le);
    },
    setFloat64: function setFloat64(offset, value, le) {
      set(this, Float64Array, 8, offset, value, le);
    }
  };
  function get(view, type, size, offset, le) {
    if (offset === undefined)
      fail('Missing required offset argument');
    if (offset < 0 || offset + size > view.byteLength)
      fail('Invalid index: ' + offset);
    if (size === 1 || !(!le) === nativele) {
      if ((view.byteOffset + offset) % size === 0)
        return new type(view.buffer, view.byteOffset + offset, 1)[0];
      else {
        for (var i = 0; i < size; i++)
          temp[i] = view._bytes[offset + i];
        return new type(temp.buffer)[0];
      }
    } else {
      for (var i = 0; i < size; i++)
        temp[size - i - 1] = view._bytes[offset + i];
      return new type(temp.buffer)[0];
    }
  }
  function set(view, type, size, offset, value, le) {
    if (offset === undefined)
      fail('Missing required offset argument');
    if (value === undefined)
      fail('Missing required value argument');
    if (offset < 0 || offset + size > view.byteLength)
      fail('Invalid index: ' + offset);
    if (size === 1 || !(!le) === nativele) {
      if ((view.byteOffset + offset) % size === 0) {
        new type(view.buffer, view.byteOffset + offset, 1)[0] = value;
      } else {
        new type(temp.buffer)[0] = value;
        for (var i = 0; i < size; i++)
          view._bytes[i + offset] = temp[i];
      }
    } else {
      new type(temp.buffer)[0] = value;
      for (var i = 0; i < size; i++)
        view._bytes[offset + i] = temp[size - 1 - i];
    }
  }
  function fail(msg) {
    throw new Error(msg);
  }
}(this));
;
var ByteArray = ByteArray || function (undefined) {
    ByteArrayClass.INITIAL_SIZE = 128;
    ByteArrayClass.DEFAULT_OBJECT_ENCODING = 3;
    function ByteArrayClass(bytes) {
      if (bytes instanceof ByteArray) {
        return bytes;
      }
      var initData = bytes || this.symbol && this.symbol.data;
      if (initData) {
        this.a = new ArrayBuffer(initData.length);
        this.length = initData.length;
        new Uint8Array(this.a).set(initData);
      } else {
        this.a = new ArrayBuffer(ByteArrayClass.INITIAL_SIZE);
        this.length = 0;
      }
      this.position = 0;
      this.cacheViews();
      this.nativele = new Int8Array(new Int32Array([]).buffer)[0] === 1;
      this.le = this.nativele;
      this.objectEncoding = ByteArrayClass.DEFAULT_OBJECT_ENCODING;
      this.bitBuffer = 0;
      this.bitLength = 0;
    }
    ;
    function throwEOFError() {
      runtime.throwErrorFromVM('flash.errors.EOFError', 'End of file was encountered.');
    }
    function throwRangeError() {
      var error = Errors.ParamRangeError;
      runtime.throwErrorFromVM('RangeError', getErrorMessage(error.code), error.code);
    }
    function throwCompressedDataError() {
      var error = Errors.CompressedDataError;
      runtime.throwErrorFromVM('CompressedDataError', getErrorMessage(error.code), error.code);
    }
    function checkRange(x, min, max) {
      if (x !== clamp(x, min, max)) {
        throwRangeError();
      }
    }
    function get(b, m, size) {
      if (b.position + size > b.length) {
        throwEOFError();
      }
      var v = b.view[m](b.position, b.le);
      b.position += size;
      return v;
    }
    function set(b, m, size, v) {
      var len = b.position + size;
      b.ensureCapacity(len);
      b.view[m](b.position, v, b.le);
      b.position = len;
      if (len > b.length) {
        b.length = len;
      }
    }
    var BAp = ByteArrayClass.prototype;
    BAp.cacheViews = function cacheViews() {
      var a = this.a;
      this.int8v = new Int8Array(a);
      this.uint8v = new Uint8Array(a);
      this.view = new DataView(a);
    };
    BAp.getBytes = function getBytes() {
      return new Uint8Array(this.a, 0, this.length);
    };
    BAp.ensureCapacity = function ensureCapacity(size) {
      var origa = this.a;
      if (origa.byteLength < size) {
        var newSize = origa.byteLength;
        while (newSize < size) {
          newSize *= 2;
        }
        var copya = new ArrayBuffer(newSize);
        var origv = this.int8v;
        this.a = copya;
        this.cacheViews();
        this.int8v.set(origv);
      }
    };
    BAp.clear = function clear() {
      this.length = 0;
      this.position = 0;
    };
    BAp.readBoolean = function readBoolean() {
      if (this.position + 1 > this.length) {
        throwEOFError();
      }
      return this.int8v[this.position++] !== 0;
    };
    BAp.readByte = function readByte() {
      if (this.position + 1 > this.length) {
        throwEOFError();
      }
      return this.int8v[this.position++];
    };
    BAp.readUnsignedByte = function readUnsignedByte() {
      if (this.position + 1 > this.length) {
        throwEOFError();
      }
      return this.uint8v[this.position++];
    };
    BAp.readBytes = function readBytes(bytes, offset, length) {
      var pos = this.position;
      if (!offset) {
        offset = 0;
      }
      if (!length) {
        length = this.length - pos;
      }
      if (pos + length > this.length) {
        throwEOFError();
      }
      if (bytes.length < offset + length) {
        bytes.ensureCapacity(offset + length);
        bytes.length = offset + length;
      }
      bytes.int8v.set(new Int8Array(this.a, pos, length), offset);
      this.position += length;
    };
    BAp.writeBoolean = function writeBoolean(v) {
      var len = this.position + 1;
      this.ensureCapacity(len);
      this.int8v[this.position++] = v ? 1 : 0;
      if (len > this.length) {
        this.length = len;
      }
    };
    BAp.writeByte = function writeByte(v) {
      var len = this.position + 1;
      this.ensureCapacity(len);
      this.int8v[this.position++] = v;
      if (len > this.length) {
        this.length = len;
      }
    };
    BAp.writeUnsignedByte = function writeUnsignedByte(v) {
      var len = this.position + 1;
      this.ensureCapacity(len);
      this.uint8v[this.position++] = v;
      if (len > this.length) {
        this.length = len;
      }
    };
    BAp.writeRawBytes = function writeRawBytes(bytes) {
      var len = this.position + bytes.length;
      this.ensureCapacity(len);
      this.int8v.set(bytes, this.position);
      this.position = len;
      if (len > this.length) {
        this.length = len;
      }
    };
    BAp.readRawBytes = function readRawBytes() {
      return new Int8Array(this.a, 0, this.length);
    };
    BAp.writeBytes = function writeBytes(bytes, offset, length) {
      if (arguments.length < 2) {
        offset = 0;
      }
      if (arguments.length < 3) {
        length = 0;
      }
      checkRange(offset, 0, bytes.length);
      checkRange(offset + length, 0, bytes.length);
      if (length === 0) {
        length = bytes.length - offset;
      }
      this.writeRawBytes(new Int8Array(bytes.a, offset, length));
    };
    BAp.readDouble = function readDouble() {
      return get(this, 'getFloat64', 8);
    };
    BAp.readFloat = function readFloat() {
      return get(this, 'getFloat32', 4);
    };
    BAp.readInt = function readInt() {
      return get(this, 'getInt32', 4);
    };
    BAp.readShort = function readShort() {
      return get(this, 'getInt16', 2);
    };
    BAp.readUnsignedInt = function readUnsignedInt() {
      return get(this, 'getUint32', 4);
    };
    BAp.readUnsignedShort = function readUnsignedShort() {
      return get(this, 'getUint16', 2);
    };
    BAp.writeDouble = function writeDouble(v) {
      set(this, 'setFloat64', 8, v);
    };
    BAp.writeFloat = function writeFloat(v) {
      set(this, 'setFloat32', 4, v);
    };
    BAp.writeInt = function writeInt(v) {
      set(this, 'setInt32', 4, v);
    };
    BAp.writeShort = function writeShort(v) {
      set(this, 'setInt16', 2, v);
    };
    BAp.writeUnsignedInt = function writeUnsignedInt(v) {
      set(this, 'setUint32', 4, v);
    };
    BAp.writeUnsignedShort = function writeUnsignedShort(v) {
      set(this, 'setUint16', 2, v);
    };
    var codeLengthOrder = [
        16,
        17,
        18,
        0,
        8,
        7,
        9,
        6,
        10,
        5,
        11,
        4,
        12,
        3,
        13,
        2,
        14,
        1,
        15
      ];
    var distanceCodes = [];
    var distanceExtraBits = [];
    for (var i = 0, j = 0, code = 1; i < 30; ++i) {
      distanceCodes[i] = code;
      code += 1 << (distanceExtraBits[i] = ~(~((j += i > 2 ? 1 : 0) / 2)));
    }
    var bitLengths = [];
    for (var i = 0; i < 32; ++i) {
      bitLengths[i] = 5;
    }
    var fixedDistanceTable = makeHuffmanTable(bitLengths);
    var lengthCodes = [];
    var lengthExtraBits = [];
    for (var i = 0, j = 0, code = 3; i < 29; ++i) {
      lengthCodes[i] = code - (i == 28 ? 1 : 0);
      code += 1 << (lengthExtraBits[i] = ~(~((j += i > 4 ? 1 : 0) / 4 % 6)));
    }
    for (var i = 0; i < 288; ++i) {
      bitLengths[i] = i < 144 || i > 279 ? 8 : i < 256 ? 9 : 7;
    }
    var fixedLiteralTable = makeHuffmanTable(bitLengths);
    function makeHuffmanTable(bitLengths) {
      var maxBits = Math.max.apply(null, bitLengths);
      var numLengths = bitLengths.length;
      var size = 1 << maxBits;
      var codes = new Uint32Array(size);
      for (var code = 0, len = 1, skip = 2; len <= maxBits; code <<= 1, ++len, skip <<= 1) {
        for (var val = 0; val < numLengths; ++val) {
          if (bitLengths[val] === len) {
            var lsb = 0;
            for (var i = 0; i < len; ++i) {
              lsb = lsb * 2 + (code >> i & 1);
            }
            for (var i = lsb; i < size; i += skip) {
              codes[i] = len << 16 | val;
            }
            ++code;
          }
        }
      }
      return {
        codes: codes,
        maxBits: maxBits
      };
    }
    function inflateBlock(input, output) {
      var header = readBits(input, 3);
      switch (header >> 1) {
      case 0:
        input.bitBuffer = input.bitLength = 0;
        var len = input.readUnsignedShort();
        var nlen = input.readUnsignedShort();
        if ((~nlen & 65535) !== len) {
          throwCompressedDataError();
        }
        output.writeBytes(input, input.position, len);
        input.position += len;
        break;
      case 1:
        inflate(input, output, fixedLiteralTable, fixedDistanceTable);
        break;
      case 2:
        var bitLengths = [];
        var numLiteralCodes = readBits(input, 5) + 257;
        var numDistanceCodes = readBits(input, 5) + 1;
        var numCodes = numLiteralCodes + numDistanceCodes;
        var numLengthCodes = readBits(input, 4) + 4;
        for (var i = 0; i < 19; ++i) {
          bitLengths[codeLengthOrder[i]] = i < numLengthCodes ? readBits(input, 3) : 0;
        }
        var codeLengthTable = makeHuffmanTable(bitLengths);
        bitLengths = [];
        var i = 0;
        var prev = 0;
        while (i < numCodes) {
          var j = 1;
          var sym = readCode(input, codeLengthTable);
          switch (sym) {
          case 16:
            j = readBits(input, 2) + 3;
            sym = prev;
            break;
          case 17:
            j = readBits(input, 3) + 3;
            sym = 0;
            break;
          case 18:
            j = readBits(input, 7) + 11;
            sym = 0;
            break;
          default:
            prev = sym;
          }
          while (j--) {
            bitLengths[i++] = sym;
          }
        }
        var distanceTable = makeHuffmanTable(bitLengths.splice(numLiteralCodes, numDistanceCodes));
        var literalTable = makeHuffmanTable(bitLengths);
        inflate(input, output, literalTable, distanceTable);
        break;
      default:
        fail('unknown block type', 'inflate');
      }
    }
    function readBits(input, size) {
      var buffer = input.bitBuffer;
      var bufflen = input.bitLength;
      while (size > bufflen) {
        buffer |= input.readUnsignedByte() << bufflen;
        bufflen += 8;
      }
      input.bitBuffer = buffer >>> size;
      input.bitLength = bufflen - size;
      return buffer & (1 << size) - 1;
    }
    function inflate(input, output, literalTable, distanceTable) {
      var sym;
      while ((sym = readCode(input, literalTable)) !== 256) {
        if (sym < 256) {
          output.writeUnsignedByte(sym);
        } else {
          sym -= 257;
          var len = lengthCodes[sym] + readBits(input, lengthExtraBits[sym]);
          sym = readCode(input, distanceTable);
          var distance = distanceCodes[sym] + readBits(input, distanceExtraBits[sym]);
          output.writeBytes(output, output.position - distance, len);
        }
      }
    }
    function readCode(input, codeTable) {
      var buffer = input.bitBuffer;
      var bitlen = input.bitLength;
      var maxBits = codeTable.maxBits;
      while (maxBits > bitlen) {
        buffer |= input.readUnsignedByte() << bitlen;
        bitlen += 8;
      }
      var code = codeTable.codes[buffer & (1 << maxBits) - 1];
      var len = code >> 16;
      if (!len) {
        throwCompressedDataError();
      }
      input.bitBuffer = buffer >>> len;
      input.bitLength = bitlen - len;
      return code & 65535;
    }
    function adler32(data, start, end) {
      var a = 1;
      var b = 0;
      for (var i = start; i < end; ++i) {
        a = (a + (data[i] & 255)) % 65521;
        b = (b + a) % 65521;
      }
      return b << 16 | a;
    }
    BAp.compress = function (algorithm) {
      this.position = 0;
      var output = new ByteArray();
      switch (algorithm) {
      case 'zlib':
        output.writeUnsignedByte(120);
        output.writeUnsignedByte(156);
      case 'deflate':
        output.le = true;
        var len = this.length;
        output.ensureCapacity(len + Math.ceil(len / 65535) * 5 + 4);
        while (len > 65535) {
          output.writeUnsignedByte(0);
          output.writeUnsignedShort(65535);
          output.writeUnsignedShort(0);
          output.writeBytes(this, this.position, 65535);
          this.position += 65535;
          len -= 65535;
        }
        output.writeUnsignedByte(0);
        output.writeUnsignedShort(len);
        output.writeUnsignedShort(~len & 65535);
        output.writeBytes(this, this.position, len);
        if (algorithm === 'zlib') {
          output.writeUnsignedInt(adler32(this.uint8v, 0, this.length));
        }
        break;
      default:
        return;
      }
      this.ensureCapacity(output.uint8v.length);
      this.uint8v.set(output.uint8v);
      this.length = output.length;
      this.position = 0;
    };
    BAp.uncompress = function (algorithm) {
      var output = new ByteArray();
      switch (algorithm) {
      case 'zlib':
        var header = this.readUnsignedShort();
        if ((header & 3840) !== 2048 || header % 31 !== 0 || header & 32) {
          throwCompressedDataError();
        }
      case 'deflate':
        var le = this.le;
        this.le = true;
        while (this.position < this.length - 6) {
          inflateBlock(this, output);
        }
        this.le = le;
        break;
      default:
        return;
      }
      this.ensureCapacity(output.uint8v.length);
      this.uint8v.set(output.uint8v);
      this.length = output.length;
      this.position = 0;
    };
    return ByteArrayClass;
  }();
var Shumway;
(function (Shumway) {
  (function (Options) {
    var Argument = function () {
        function Argument(shortName, longName, type, options) {
          this.shortName = shortName;
          this.longName = longName;
          this.type = type;
          options = options || {};
          this.positional = options.positional;
          this.parseFn = options.parse;
          this.value = options.defaultValue;
        }
        Argument.prototype.parse = function (value) {
          if (this.type === 'boolean') {
            true;
            this.value = value;
          } else if (this.type === 'number') {
            true;
            this.value = parseInt(value, 10);
          } else {
            this.value = value;
          }
          if (this.parseFn) {
            this.parseFn(this.value);
          }
        };
        return Argument;
      }();
    Options.Argument = Argument;
    var ArgumentParser = function () {
        function ArgumentParser() {
          this.args = [];
        }
        ArgumentParser.prototype.addArgument = function (shortName, longName, type, options) {
          var argument = new Argument(shortName, longName, type, options);
          this.args.push(argument);
          return argument;
        };
        ArgumentParser.prototype.addBoundOption = function (option) {
          var options = {
              parse: function (x) {
                option.value = x;
              }
            };
          this.args.push(new Argument(option.shortName, option.longName, option.type, options));
        };
        ArgumentParser.prototype.addBoundOptionSet = function (optionSet) {
          var self = this;
          optionSet.options.forEach(function (x) {
            if (x instanceof OptionSet) {
              self.addBoundOptionSet(x);
            } else {
              true;
              self.addBoundOption(x);
            }
          });
        };
        ArgumentParser.prototype.getUsage = function () {
          var str = '';
          this.args.forEach(function (x) {
            if (!x.positional) {
              str += '[-' + x.shortName + '|--' + x.longName + (x.type === 'boolean' ? '' : ' ' + x.type[0].toUpperCase()) + ']';
            } else {
              str += x.longName;
            }
            str += ' ';
          });
          return str;
        };
        ArgumentParser.prototype.parse = function (args) {
          var nonPositionalArgumentMap = {};
          var positionalArgumentList = [];
          this.args.forEach(function (x) {
            if (x.positional) {
              positionalArgumentList.push(x);
            } else {
              nonPositionalArgumentMap['-' + x.shortName] = x;
              nonPositionalArgumentMap['--' + x.longName] = x;
            }
          });
          var leftoverArguments = [];
          while (args.length) {
            var argString = args.shift();
            var argument = null, value = argString;
            if (argString == '--') {
              leftoverArguments = leftoverArguments.concat(args);
              break;
            } else if (argString.slice(0, 1) == '-' || argString.slice(0, 2) == '--') {
              argument = nonPositionalArgumentMap[argString];
              true;
              if (!argument) {
                continue;
              }
              if (argument.type !== 'boolean') {
                value = args.shift();
                true;
              } else {
                value = true;
              }
            } else if (positionalArgumentList.length) {
              argument = positionalArgumentList.shift();
            } else {
              leftoverArguments.push(value);
            }
            if (argument) {
              argument.parse(value);
            }
          }
          true;
          return leftoverArguments;
        };
        return ArgumentParser;
      }();
    Options.ArgumentParser = ArgumentParser;
    var OptionSet = function () {
        function OptionSet(name) {
          this.name = name;
          this.options = [];
        }
        OptionSet.prototype.register = function (option) {
          this.options.push(option);
          return option;
        };
        OptionSet.prototype.trace = function (writer) {
          writer.enter(this.name + ' {');
          this.options.forEach(function (option) {
            option.trace(writer);
          });
          writer.leave('}');
        };
        return OptionSet;
      }();
    Options.OptionSet = OptionSet;
    var Option = function () {
        function Option(shortName, longName, type, defaultValue, description) {
          this.longName = longName;
          this.shortName = shortName;
          this.type = type;
          this.defaultValue = defaultValue;
          this.value = defaultValue;
          this.description = description;
        }
        Option.prototype.parse = function (value) {
          this.value = value;
        };
        Option.prototype.trace = function (writer) {
          writer.writeLn(('-' + this.shortName + '|--' + this.longName).padRight(' ', 30) + ' = ' + this.type + ' ' + this.value + ' [' + this.defaultValue + ']' + ' (' + this.description + ')');
        };
        return Option;
      }();
    Options.Option = Option;
  }(Shumway.Options || (Shumway.Options = {})));
  var Options = Shumway.Options;
}(Shumway || (Shumway = {})));
if (typeof exports !== 'undefined') {
  exports['Shumway'] = Shumway;
}
var ArgumentParser = Shumway.Options.ArgumentParser;
var Option = Shumway.Options.Option;
var OptionSet = Shumway.Options.OptionSet;
var Option = Shumway.Options.Option;
var OptionSet = Shumway.Options.OptionSet;
var coreOptions = new OptionSet('Core Options');
var Timeline = function () {
    var barColor = 'rgba(255,255,255, 0.075)';
    var backgroundColor = 'rgb(61, 61, 61)';
    var backgroundColorInfo = 'rgba(0,0,0, 0.85)';
    var fpsLineColor = 'rgb(255,64,0)';
    var textColor = '#ccc';
    function timeline(canvas) {
      this.depth = 0;
      this.start = 0;
      this.index = 0;
      this.marks = new Shumway.CircularBuffer(Int32Array);
      this.times = new Shumway.CircularBuffer(Float64Array);
      this.frameRate = 12;
      this.maxFrameTime = 1000 * 2 / this.frameRate;
      this.refreshFrequency = 10;
      this.refreshCounter = 0;
      this.count = 0;
      this.kinds = createEmptyObject();
      this.kindCount = 0;
      this.canvas = canvas;
      this.context = canvas.getContext('2d', {
        original: true
      });
      this.fillStyles = [
        'rgb(85, 152, 213)',
        '#bfd8a7',
        '#d906d7'
      ];
      window.addEventListener('resize', this.resizeHandler.bind(this), false);
      this.resizeHandler();
    }
    timeline.prototype.setFrameRate = function setFrameRate(frameRate) {
      this.frameRate = frameRate;
      this.maxFrameTime = 1000 * 2 / frameRate;
    };
    timeline.prototype.refreshEvery = function refreshEvery(freq) {
      this.refreshFrequency = freq;
      this.refreshCounter = 0;
    };
    var ENTER = 3203334144 | 0;
    var LEAVE = 3735879680 | 0;
    timeline.prototype.registerKind = function getKind(name, fillStyle) {
      if (this.kinds[name] === undefined) {
        this.fillStyles[this.kindCount] = fillStyle;
        this.kinds[name] = this.kindCount++;
      } else {
        this.fillStyles[this.kinds[name]] = fillStyle;
      }
    };
    timeline.prototype.getKind = function getKind(name) {
      if (this.kinds[name] === undefined) {
        this.kinds[name] = this.kindCount++;
        if (this.kindCount > this.fillStyles.length) {
          this.fillStyles.push(randomStyle());
        }
      }
      return this.kinds[name];
    };
    timeline.prototype.enter = function enter(name) {
      this.depth++;
      this.marks.write(ENTER | this.getKind(name));
      this.times.write(performance.now());
    };
    timeline.prototype.leave = function leave(name) {
      this.marks.write(LEAVE | this.getKind(name));
      this.times.write(performance.now());
      this.depth--;
      if (this.depth === 0) {
        this.count++;
        if (++this.refreshCounter == this.refreshFrequency) {
          this.refreshCounter = 0;
          this.paint();
        }
      }
    };
    timeline.prototype.gatherFrames = function gatherFrames(maxFrames) {
      var stack = [];
      var frames = [];
      var times = this.times;
      maxFrames++;
      this.marks.forEachInReverse(function (mark, i) {
        var time = times.get(i);
        if ((mark & 4294901760) === ENTER) {
          var node = stack.pop();
          node.startTime = time;
          if (!stack.length) {
            if (frames.length && !frames[0].total) {
              frames[0].total = frames[0].startTime - time;
            }
            frames.unshift(node);
          } else {
            var top = stack.top();
            if (!top.children) {
              top.children = [
                node
              ];
            } else {
              top.children.push(node);
            }
          }
        } else if ((mark & 4294901760) === LEAVE) {
          if (frames.length > maxFrames) {
            return true;
          }
          stack.push({
            kind: mark & 65535,
            endTime: time
          });
        }
      });
      return frames;
    };
    timeline.prototype.resizeHandler = function resizeHandler(event) {
      var parent = this.canvas.parentElement;
      this.cw = parent.offsetWidth;
      this.ch = parent.offsetHeight - 1;
      var devicePixelRatio = window.devicePixelRatio || 1;
      var backingStoreRatio = this.context.webkitBackingStorePixelRatio || this.context.mozBackingStorePixelRatio || this.context.msBackingStorePixelRatio || this.context.oBackingStorePixelRatio || this.context.backingStorePixelRatio || 1;
      if (devicePixelRatio !== backingStoreRatio) {
        var ratio = devicePixelRatio / backingStoreRatio;
        this.canvas.width = this.cw * ratio;
        this.canvas.height = this.ch * ratio;
        this.canvas.style.width = this.cw + 'px';
        this.canvas.style.height = this.ch + 'px';
        this.context.scale(ratio, ratio);
      } else {
        this.canvas.width = this.cw;
        this.canvas.height = this.ch;
      }
      this.context.font = '10px Consolas, "Liberation Mono", Courier, monospace';
    };
    timeline.prototype.paint = function paint() {
      var w = 10;
      var gap = 1;
      var maxFrames = this.cw / (w + gap) | 0;
      var frames = this.gatherFrames(maxFrames);
      var context = this.context;
      var maxFrameTime = this.maxFrameTime;
      var fillStyles = this.fillStyles;
      context.clearRect(0, 0, this.cw, this.ch);
      var maxFrameRate = 0;
      var maxFrameRateCount = 0;
      var avgFrameRate = 0;
      var avgFrameRateCount = 0;
      var offsetW;
      context.save();
      context.translate(0, this.ch);
      context.scale(1, -this.ch / maxFrameTime);
      for (var i = 0; i < frames.length - 1; i++) {
        var frame = frames[i];
        maxFrameRate += frame.endTime - frame.startTime;
        maxFrameRateCount++;
        if (frame.total) {
          avgFrameRate += frame.total;
          avgFrameRateCount++;
        }
        offsetW = i * (w + gap);
        context.fillStyle = barColor;
        context.fillRect(offsetW, 0, w, frames[i + 1].startTime - frame.startTime);
        drawNode(frame, frame.startTime);
      }
      function drawNode(node, frameStartTime) {
        var nodeTime = node.endTime - node.startTime;
        var offsetH = node.startTime - frameStartTime;
        context.fillStyle = fillStyles[node.kind];
        context.fillRect(offsetW, offsetH, w, nodeTime);
        if (node.children) {
          var children = node.children;
          for (var i = 0, n = children.length; i < n; i++) {
            drawNode(children[i], frameStartTime);
          }
        }
      }
      var lineH = 1000 / this.frameRate;
      context.beginPath();
      context.lineWidth = 0.5;
      context.moveTo(0, lineH);
      context.lineTo(this.cw, lineH);
      context.strokeStyle = fpsLineColor;
      context.stroke();
      context.restore();
      context.fillStyle = backgroundColorInfo;
      context.fillRect(0, 0, this.cw, 20);
      var textOffset;
      var sFrameCount = this.count;
      var sMaxFrameRate = Math.round(1000 * maxFrameRateCount / maxFrameRate);
      var sAvgFrameRate = Math.round(1000 * avgFrameRateCount / avgFrameRate);
      var space = 5;
      textOffset = 5;
      context.fillStyle = textColor;
      context.fillText(sFrameCount, textOffset, 13);
      textOffset += context.measureText(sFrameCount).width + space;
      context.fillText(sMaxFrameRate, textOffset, 13);
      textOffset += context.measureText(sMaxFrameRate).width + space;
      context.fillText(sAvgFrameRate, textOffset, 13);
      var basicOffset = textOffset + context.measureText(sAvgFrameRate).width + space;
      textOffset = this.cw;
      for (var k in this.kinds) {
        context.fillStyle = this.fillStyles[this.getKind(k)];
        textOffset -= context.measureText(k).width + space;
        if (textOffset > basicOffset) {
          this.context.fillText(k, textOffset, 13);
        }
      }
    };
    return timeline;
  }();
var create = Object.create;
var defineProperty = Object.defineProperty;
var keys = Object.keys;
var isArray = Array.isArray;
var fromCharCode = String.fromCharCode;
var logE = Math.log;
var max = Math.max;
var min = Math.min;
var pow = Math.pow;
var push = Array.prototype.push;
var slice = Array.prototype.slice;
var splice = Array.prototype.splice;
function fail(msg, context) {
  throw new Error((context ? context + ': ' : '') + msg);
}
function assert(cond, msg, context) {
  if (!cond)
    fail(msg, context);
}
function scriptProperties(namespace, props) {
  return props.reduce(function (o, p) {
    o[p] = namespace + ' ' + p;
    return o;
  }, {});
}
function cloneObject(obj) {
  var clone = Object.create(null);
  for (var prop in obj)
    clone[prop] = obj[prop];
  return clone;
}
function sortNumeric(a, b) {
  return a - b;
}
function sortByZindex(a, b) {
  return a._zindex - b._zindex;
}
function rgbaObjToStr(color) {
  return 'rgba(' + color.red + ',' + color.green + ',' + color.blue + ',' + color.alpha / 255 + ')';
}
function rgbIntAlphaToStr(color, alpha) {
  color |= 0;
  if (alpha >= 1) {
    var colorStr = color.toString(16);
    while (colorStr.length < 6) {
      colorStr = '0' + colorStr;
    }
    return '#' + colorStr;
  }
  var red = color >> 16 & 255;
  var green = color >> 8 & 255;
  var blue = color & 255;
  return 'rgba(' + red + ',' + green + ',' + blue + ',' + alpha + ')';
}
function argbUintToStr(argb) {
  return 'rgba(' + (argb >>> 16 & 255) + ',' + (argb >>> 8 & 255) + ',' + (argb & 255) + ',' + (argb >>> 24 & 255) / 255 + ')';
}
(function functionNameSupport() {
  if (eval('function t() {} t.name === \'t\'')) {
    return;
  }
  Object.defineProperty(Function.prototype, 'name', {
    get: function () {
      if (this.__name) {
        return this.__name;
      }
      var m = /function\s([^\(]+)/.exec(this.toString());
      var name = m && m[1] !== 'anonymous' ? m[1] : null;
      this.__name = name;
      return name;
    },
    configurable: true,
    enumerable: false
  });
}());
var randomStyleCache;
var nextStyle = 0;
function randomStyle() {
  if (!randomStyleCache) {
    randomStyleCache = [
      '#ff5e3a',
      '#ff9500',
      '#ffdb4c',
      '#87fc70',
      '#52edc7',
      '#1ad6fd',
      '#c644fc',
      '#ef4db6',
      '#4a4a4a',
      '#dbddde',
      '#ff3b30',
      '#ff9500',
      '#ffcc00',
      '#4cd964',
      '#34aadc',
      '#007aff',
      '#5856d6',
      '#ff2d55',
      '#8e8e93',
      '#c7c7cc',
      '#5ad427',
      '#c86edf',
      '#d1eefc',
      '#e0f8d8',
      '#fb2b69',
      '#f7f7f7',
      '#1d77ef',
      '#d6cec3',
      '#55efcb',
      '#ff4981',
      '#ffd3e0',
      '#f7f7f7',
      '#ff1300',
      '#1f1f21',
      '#bdbec2',
      '#ff3a2d'
    ];
  }
  return randomStyleCache[nextStyle++ % randomStyleCache.length];
}
(function PromiseClosure() {
  var global = Function('return this')();
  if (global.Promise) {
    if (typeof global.Promise.all !== 'function') {
      global.Promise.all = function (iterable) {
        var count = 0, results = [], resolve, reject;
        var promise = new global.Promise(function (resolve_, reject_) {
            resolve = resolve_;
            reject = reject_;
          });
        iterable.forEach(function (p, i) {
          count++;
          p.then(function (result) {
            results[i] = result;
            count--;
            if (count === 0) {
              resolve(results);
            }
          }, reject);
        });
        if (count === 0) {
          resolve(results);
        }
        return promise;
      };
    }
    if (typeof global.Promise.resolve !== 'function') {
      global.Promise.resolve = function (x) {
        return new global.Promise(function (resolve) {
          resolve(x);
        });
      };
    }
    return;
  }
  function getDeferred(C) {
    if (typeof C !== 'function') {
      throw new TypeError('Invalid deferred constructor');
    }
    var resolver = createDeferredConstructionFunctions();
    var promise = new C(resolver);
    var resolve = resolver.resolve;
    if (typeof resolve !== 'function') {
      throw new TypeError('Invalid resolve construction function');
    }
    var reject = resolver.reject;
    if (typeof reject !== 'function') {
      throw new TypeError('Invalid reject construction function');
    }
    return {
      promise: promise,
      resolve: resolve,
      reject: reject
    };
  }
  function updateDeferredFromPotentialThenable(x, deferred) {
    if (typeof x !== 'object' || x === null) {
      return false;
    }
    try {
      var then = x.then;
      if (typeof then !== 'function') {
        return false;
      }
      var thenCallResult = then.call(x, deferred.resolve, deferred.reject);
    } catch (e) {
      var reject = deferred.reject;
      reject(e);
    }
    return true;
  }
  function isPromise(x) {
    return typeof x === 'object' && x !== null && typeof x.promiseStatus !== 'undefined';
  }
  function rejectPromise(promise, reason) {
    if (promise.promiseStatus !== 'unresolved') {
      return;
    }
    var reactions = promise.rejectReactions;
    promise.result = reason;
    promise.resolveReactions = undefined;
    promise.rejectReactions = undefined;
    promise.promiseStatus = 'has-rejection';
    triggerPromiseReactions(reactions, reason);
  }
  function resolvePromise(promise, resolution) {
    if (promise.promiseStatus !== 'unresolved') {
      return;
    }
    var reactions = promise.resolveReactions;
    promise.result = resolution;
    promise.resolveReactions = undefined;
    promise.rejectReactions = undefined;
    promise.promiseStatus = 'has-resolution';
    triggerPromiseReactions(reactions, resolution);
  }
  function triggerPromiseReactions(reactions, argument) {
    for (var i = 0; i < reactions.length; i++) {
      queueMicrotask({
        reaction: reactions[i],
        argument: argument
      });
    }
  }
  function queueMicrotask(task) {
    if (microtasksQueue.length === 0) {
      setTimeout(handleMicrotasksQueue, 0);
    }
    microtasksQueue.push(task);
  }
  function executePromiseReaction(reaction, argument) {
    var deferred = reaction.deferred;
    var handler = reaction.handler;
    var handlerResult, updateResult;
    try {
      handlerResult = handler(argument);
    } catch (e) {
      var reject = deferred.reject;
      return reject(e);
    }
    if (handlerResult === deferred.promise) {
      var reject = deferred.reject;
      return reject(new TypeError('Self resolution'));
    }
    try {
      updateResult = updateDeferredFromPotentialThenable(handlerResult, deferred);
      if (!updateResult) {
        var resolve = deferred.resolve;
        return resolve(handlerResult);
      }
    } catch (e) {
      var reject = deferred.reject;
      return reject(e);
    }
  }
  var microtasksQueue = [];
  function handleMicrotasksQueue() {
    while (microtasksQueue.length > 0) {
      var task = microtasksQueue[0];
      try {
        executePromiseReaction(task.reaction, task.argument);
      } catch (e) {
        if (typeof Promise.onerror === 'function') {
          Promise.onerror(e);
        }
      }
      microtasksQueue.shift();
    }
  }
  function throwerFunction(e) {
    throw e;
  }
  function identityFunction(x) {
    return x;
  }
  function createRejectPromiseFunction(promise) {
    return function (reason) {
      rejectPromise(promise, reason);
    };
  }
  function createResolvePromiseFunction(promise) {
    return function (resolution) {
      resolvePromise(promise, resolution);
    };
  }
  function createDeferredConstructionFunctions() {
    var fn = function (resolve, reject) {
      fn.resolve = resolve;
      fn.reject = reject;
    };
    return fn;
  }
  function createPromiseResolutionHandlerFunctions(promise, fulfillmentHandler, rejectionHandler) {
    return function (x) {
      if (x === promise) {
        return rejectionHandler(new TypeError('Self resolution'));
      }
      var cstr = promise.promiseConstructor;
      if (isPromise(x)) {
        var xConstructor = x.promiseConstructor;
        if (xConstructor === cstr) {
          return x.then(fulfillmentHandler, rejectionHandler);
        }
      }
      var deferred = getDeferred(cstr);
      var updateResult = updateDeferredFromPotentialThenable(x, deferred);
      if (updateResult) {
        var deferredPromise = deferred.promise;
        return deferredPromise.then(fulfillmentHandler, rejectionHandler);
      }
      return fulfillmentHandler(x);
    };
  }
  function createPromiseAllCountdownFunction(index, values, deferred, countdownHolder) {
    return function (x) {
      values[index] = x;
      countdownHolder.countdown--;
      if (countdownHolder.countdown === 0) {
        deferred.resolve(values);
      }
    };
  }
  function Promise(resolver) {
    if (typeof resolver !== 'function') {
      throw new TypeError('resolver is not a function');
    }
    var promise = this;
    if (typeof promise !== 'object') {
      throw new TypeError('Promise to initialize is not an object');
    }
    promise.promiseStatus = 'unresolved';
    promise.resolveReactions = [];
    promise.rejectReactions = [];
    promise.result = undefined;
    var resolve = createResolvePromiseFunction(promise);
    var reject = createRejectPromiseFunction(promise);
    try {
      var result = resolver(resolve, reject);
    } catch (e) {
      rejectPromise(promise, e);
    }
    promise.promiseConstructor = Promise;
    return promise;
  }
  Promise.all = function (iterable) {
    var deferred = getDeferred(this);
    var values = [];
    var countdownHolder = {
        countdown: 0
      };
    var index = 0;
    iterable.forEach(function (nextValue) {
      var nextPromise = this.cast(nextValue);
      var fn = createPromiseAllCountdownFunction(index, values, deferred, countdownHolder);
      nextPromise.then(fn, deferred.reject);
      index++;
      countdownHolder.countdown++;
    }, this);
    if (index === 0) {
      deferred.resolve(values);
    }
    return deferred.promise;
  };
  Promise.cast = function (x) {
    if (isPromise(x)) {
      return x;
    }
    var deferred = getDeferred(this);
    deferred.resolve(x);
    return deferred.promise;
  };
  Promise.reject = function (r) {
    var deferred = getDeferred(this);
    var rejectResult = deferred.reject(r);
    return deferred.promise;
  };
  Promise.resolve = function (x) {
    var deferred = getDeferred(this);
    var rejectResult = deferred.resolve(x);
    return deferred.promise;
  };
  Promise.prototype = {
    'catch': function (onRejected) {
      this.then(undefined, onRejected);
    },
    then: function (onFulfilled, onRejected) {
      var promise = this;
      if (!isPromise(promise)) {
        throw new TypeError('this is not a Promises');
      }
      var cstr = promise.promiseConstructor;
      var deferred = getDeferred(cstr);
      var rejectionHandler = typeof onRejected === 'function' ? onRejected : throwerFunction;
      var fulfillmentHandler = typeof onFulfilled === 'function' ? onFulfilled : identityFunction;
      var resolutionHandler = createPromiseResolutionHandlerFunctions(promise, fulfillmentHandler, rejectionHandler);
      var resolveReaction = {
          deferred: deferred,
          handler: resolutionHandler
        };
      var rejectReaction = {
          deferred: deferred,
          handler: rejectionHandler
        };
      switch (promise.promiseStatus) {
      case 'unresolved':
        promise.resolveReactions.push(resolveReaction);
        promise.rejectReactions.push(rejectReaction);
        break;
      case 'has-resolution':
        var resolution = promise.result;
        queueMicrotask({
          reaction: resolveReaction,
          argument: resolution
        });
        break;
      case 'has-rejection':
        var rejection = promise.result;
        queueMicrotask({
          reaction: rejectReaction,
          argument: rejection
        });
        break;
      }
      return deferred.promise;
    }
  };
  global.Promise = Promise;
}());
var QuadTree = function (x, y, width, height, parent) {
  this.x = x | 0;
  this.y = y | 0;
  this.width = width | 0;
  this.height = height | 0;
  if (parent) {
    this.root = parent.root;
    this.parent = parent;
    this.level = parent.level + 1;
  } else {
    this.root = this;
    this.parent = null;
    this.level = 0;
  }
  this.reset();
};
QuadTree.prototype.reset = function () {
  this.stuckObjects = null;
  this.objects = null;
  this.nodes = [];
};
QuadTree.prototype._findIndex = function (xMin, xMax, yMin, yMax) {
  var midX = this.x + (this.width / 2 | 0);
  var midY = this.y + (this.height / 2 | 0);
  var top = yMin < midY && yMax < midY;
  var bottom = yMin > midY;
  if (xMin < midX && xMax < midX) {
    if (top) {
      return 1;
    } else if (bottom) {
      return 2;
    }
  } else if (xMin > midX) {
    if (top) {
      return 0;
    } else if (bottom) {
      return 3;
    }
  }
  return -1;
};
QuadTree.prototype.insert = function (obj) {
  var nodes = this.nodes;
  if (nodes.length) {
    var index = this._findIndex(obj.xMin, obj.xMax, obj.yMin, obj.yMax);
    if (index > -1) {
      nodes[index].insert(obj);
    } else {
      obj.prev = null;
      if (this.stuckObjects) {
        obj.next = this.stuckObjects;
        this.stuckObjects.prev = obj;
      } else {
        obj.next = null;
      }
      this.stuckObjects = obj;
      obj.parent = this;
    }
    return;
  }
  var numChildren = 1;
  var item = this.objects;
  if (!item) {
    obj.prev = null;
    obj.next = null;
    this.objects = obj;
  } else {
    while (item.next) {
      numChildren++;
      item = item.next;
    }
    obj.prev = item;
    obj.next = null;
    item.next = obj;
  }
  if (numChildren > 4 && this.level < 10) {
    this._subdivide();
    item = this.objects;
    while (item) {
      var next = item.next;
      this.insert(item);
      item = next;
    }
    this.objects = null;
    return;
  }
  obj.parent = this;
};
QuadTree.prototype.update = function (obj) {
  var node = obj.parent;
  if (node) {
    if (obj.xMin >= node.x && obj.xMax <= node.x + node.width && obj.yMin >= node.y && obj.yMax <= node.y + node.height) {
      if (node.nodes.length) {
        var index = this._findIndex(obj.xMin, obj.xMax, obj.yMin, obj.yMax);
        if (index > -1) {
          node.remove(obj);
          node = this.nodes[index];
          node.insert(obj);
        }
      } else {
        node.remove(obj);
        node.insert(obj);
      }
      return;
    }
    node.remove(obj);
  }
  this.root.insert(obj);
};
QuadTree.prototype.remove = function (obj) {
  var prev = obj.prev;
  var next = obj.next;
  if (prev) {
    prev.next = next;
    obj.prev = null;
  } else {
    var node = obj.parent;
    if (node.objects === obj) {
      node.objects = next;
    } else if (node.stuckObjects === obj) {
      node.stuckObjects = next;
    }
  }
  if (next) {
    next.prev = prev;
    obj.next = null;
  }
  obj.parent = null;
};
QuadTree.prototype.retrieve = function (xMin, xMax, yMin, yMax) {
  var stack = [];
  var out = [];
  var node = this;
  do {
    if (node.nodes.length) {
      var index = node._findIndex(xMin, xMax, yMin, yMax);
      if (index > -1) {
        stack.push(node.nodes[index]);
      } else {
        stack.push.apply(stack, node.nodes);
      }
    }
    var item = node.objects;
    for (var i = 0; i < 2; i++) {
      while (item) {
        if (!(item.xMin > xMax || item.xMax < xMin || item.yMin > yMax || item.yMax < yMin)) {
          out.push(item);
        }
        item = item.next;
      }
      item = node.stuckObjects;
    }
    node = stack.pop();
  } while (node);
  return out;
};
QuadTree.prototype._subdivide = function () {
  var halfWidth = this.width / 2 | 0;
  var halfHeight = this.height / 2 | 0;
  var midX = this.x + halfWidth;
  var midY = this.y + halfHeight;
  this.nodes[0] = new QuadTree(midX, this.y, halfWidth, halfHeight, this);
  this.nodes[1] = new QuadTree(this.x, this.y, halfWidth, halfHeight, this);
  this.nodes[2] = new QuadTree(this.x, midY, halfWidth, halfHeight, this);
  this.nodes[3] = new QuadTree(midX, midY, halfWidth, halfHeight, this);
};
var RegionCluster = function () {
  this.regions = [];
};
RegionCluster.prototype.reset = function () {
  this.regions.length = 0;
};
RegionCluster.prototype.insert = function (region) {
  var regions = this.regions;
  if (regions.length < 3) {
    regions.push({
      xMin: region.xMin,
      xMax: region.xMax,
      yMin: region.yMin,
      yMax: region.yMax
    });
    return;
  }
  var a = region;
  var b = regions[0];
  var c = regions[1];
  var d = regions[2];
  var ab = (max(a.xMax, b.xMax) - min(a.xMin, b.xMin)) * (max(a.yMax, b.yMax) - min(a.yMin, b.yMin));
  var rb = regions[0];
  var ac = (max(a.xMax, c.xMax) - min(a.xMin, c.xMin)) * (max(a.yMax, c.yMax) - min(a.yMin, c.yMin));
  var ad = (max(a.xMax, d.xMax) - min(a.xMin, d.xMin)) * (max(a.yMax, d.yMax) - min(a.yMin, d.yMin));
  if (ac < ab) {
    ab = ac;
    rb = c;
  }
  if (ad < ab) {
    ab = ad;
    rb = d;
  }
  var bc = (max(b.xMax, c.xMax) - min(b.xMin, c.xMin)) * (max(b.yMax, c.yMax) - min(b.yMin, c.yMin));
  var bd = (max(b.xMax, d.xMax) - min(b.xMin, d.xMin)) * (max(b.yMax, d.yMax) - min(b.yMin, d.yMin));
  var cd = (max(c.xMax, d.xMax) - min(c.xMin, d.xMin)) * (max(c.yMax, d.yMax) - min(c.yMin, d.yMin));
  if (ab < bc && ab < bd && ab < cd) {
    if (a.xMin < rb.xMin) {
      rb.xMin = a.xMin;
    }
    if (a.xMax > rb.xMax) {
      rb.xMax = a.xMax;
    }
    if (a.yMin < rb.yMin) {
      rb.yMin = a.yMin;
    }
    if (a.yMax > rb.yMax) {
      rb.yMax = a.yMax;
    }
    return;
  }
  rb = regions[0];
  var rc = regions[1];
  if (bd < bc) {
    bc = bd;
    rc = regions[2];
  }
  if (cd < bc) {
    rb = regions[1];
    rc = regions[2];
  }
  if (rc.xMin < rb.xMin) {
    rb.xMin = rc.xMin;
  }
  if (rc.xMax > rb.xMax) {
    rb.xMax = rc.xMax;
  }
  if (rc.yMin < rb.yMin) {
    rb.yMin = rc.yMin;
  }
  if (rc.yMax > rb.yMax) {
    rb.yMax = rc.yMax;
  }
  rc.xMin = a.xMin;
  rc.xMax = a.xMax;
  rc.yMin = a.yMin;
  rc.yMax = a.yMax;
};
RegionCluster.prototype.retrieve = function () {
  return this.regions;
};
var EXTERNAL_INTERFACE_FEATURE = 1;
var CLIPBOARD_FEATURE = 2;
var SHAREDOBJECT_FEATURE = 3;
var VIDEO_FEATURE = 4;
var SOUND_FEATURE = 5;
var NETCONNECTION_FEATURE = 6;
if (!this.performance) {
  this.performance = {};
}
if (!this.performance.now) {
  this.performance.now = Date.now;
}
var SWF_TAG_CODE_CSM_TEXT_SETTINGS = 74;
var SWF_TAG_CODE_DEFINE_BINARY_DATA = 87;
var SWF_TAG_CODE_DEFINE_BITS = 6;
var SWF_TAG_CODE_DEFINE_BITS_JPEG2 = 21;
var SWF_TAG_CODE_DEFINE_BITS_JPEG3 = 35;
var SWF_TAG_CODE_DEFINE_BITS_JPEG4 = 90;
var SWF_TAG_CODE_DEFINE_BITS_LOSSLESS = 20;
var SWF_TAG_CODE_DEFINE_BITS_LOSSLESS2 = 36;
var SWF_TAG_CODE_DEFINE_BUTTON = 7;
var SWF_TAG_CODE_DEFINE_BUTTON2 = 34;
var SWF_TAG_CODE_DEFINE_BUTTON_CXFORM = 23;
var SWF_TAG_CODE_DEFINE_BUTTON_SOUND = 17;
var SWF_TAG_CODE_DEFINE_EDIT_TEXT = 37;
var SWF_TAG_CODE_DEFINE_FONT = 10;
var SWF_TAG_CODE_DEFINE_FONT2 = 48;
var SWF_TAG_CODE_DEFINE_FONT3 = 75;
var SWF_TAG_CODE_DEFINE_FONT4 = 91;
var SWF_TAG_CODE_DEFINE_FONT_ALIGN_ZONES = 73;
var SWF_TAG_CODE_DEFINE_FONT_INFO = 13;
var SWF_TAG_CODE_DEFINE_FONT_INFO2 = 62;
var SWF_TAG_CODE_DEFINE_FONT_NAME = 88;
var SWF_TAG_CODE_DEFINE_MORPH_SHAPE = 46;
var SWF_TAG_CODE_DEFINE_MORPH_SHAPE2 = 84;
var SWF_TAG_CODE_DEFINE_SCALING_GRID = 78;
var SWF_TAG_CODE_DEFINE_SCENE_AND_FRAME_LABEL_DATA = 86;
var SWF_TAG_CODE_DEFINE_SHAPE = 2;
var SWF_TAG_CODE_DEFINE_SHAPE2 = 22;
var SWF_TAG_CODE_DEFINE_SHAPE3 = 32;
var SWF_TAG_CODE_DEFINE_SHAPE4 = 83;
var SWF_TAG_CODE_DEFINE_SOUND = 14;
var SWF_TAG_CODE_DEFINE_SPRITE = 39;
var SWF_TAG_CODE_DEFINE_TEXT = 11;
var SWF_TAG_CODE_DEFINE_TEXT2 = 33;
var SWF_TAG_CODE_DEFINE_VIDEO_STREAM = 60;
var SWF_TAG_CODE_DO_ABC = 82;
var SWF_TAG_CODE_DO_ABC_ = 72;
var SWF_TAG_CODE_DO_ACTION = 12;
var SWF_TAG_CODE_DO_INIT_ACTION = 59;
var SWF_TAG_CODE_ENABLE_DEBUGGER = 58;
var SWF_TAG_CODE_ENABLE_DEBUGGER2 = 64;
var SWF_TAG_CODE_END = 0;
var SWF_TAG_CODE_EXPORT_ASSETS = 56;
var SWF_TAG_CODE_FILE_ATTRIBUTES = 69;
var SWF_TAG_CODE_FRAME_LABEL = 43;
var SWF_TAG_CODE_IMPORT_ASSETS = 57;
var SWF_TAG_CODE_IMPORT_ASSETS2 = 71;
var SWF_TAG_CODE_JPEG_TABLES = 8;
var SWF_TAG_CODE_METADATA = 77;
var SWF_TAG_CODE_PLACE_OBJECT = 4;
var SWF_TAG_CODE_PLACE_OBJECT2 = 26;
var SWF_TAG_CODE_PLACE_OBJECT3 = 70;
var SWF_TAG_CODE_PROTECT = 24;
var SWF_TAG_CODE_REMOVE_OBJECT = 5;
var SWF_TAG_CODE_REMOVE_OBJECT2 = 28;
var SWF_TAG_CODE_SCRIPT_LIMITS = 65;
var SWF_TAG_CODE_SET_BACKGROUND_COLOR = 9;
var SWF_TAG_CODE_SET_TAB_INDEX = 66;
var SWF_TAG_CODE_SHOW_FRAME = 1;
var SWF_TAG_CODE_SOUND_STREAM_BLOCK = 19;
var SWF_TAG_CODE_SOUND_STREAM_HEAD = 18;
var SWF_TAG_CODE_SOUND_STREAM_HEAD2 = 45;
var SWF_TAG_CODE_START_SOUND = 15;
var SWF_TAG_CODE_START_SOUND2 = 89;
var SWF_TAG_CODE_SYMBOL_CLASS = 76;
var SWF_TAG_CODE_VIDEO_FRAME = 61;
self.SWF = {};
var codeLengthOrder = [
    16,
    17,
    18,
    0,
    8,
    7,
    9,
    6,
    10,
    5,
    11,
    4,
    12,
    3,
    13,
    2,
    14,
    1,
    15
  ];
var distanceCodes = [];
var distanceExtraBits = [];
for (var i = 0, j = 0, code = 1; i < 30; ++i) {
  distanceCodes[i] = code;
  code += 1 << (distanceExtraBits[i] = ~(~((j += i > 2 ? 1 : 0) / 2)));
}
var bitLengths = [];
for (var i = 0; i < 32; ++i)
  bitLengths[i] = 5;
var fixedDistanceTable = makeHuffmanTable(bitLengths);
var lengthCodes = [];
var lengthExtraBits = [];
for (var i = 0, j = 0, code = 3; i < 29; ++i) {
  lengthCodes[i] = code - (i == 28 ? 1 : 0);
  code += 1 << (lengthExtraBits[i] = ~(~((j += i > 4 ? 1 : 0) / 4 % 6)));
}
for (var i = 0; i < 288; ++i)
  bitLengths[i] = i < 144 || i > 279 ? 8 : i < 256 ? 9 : 7;
var fixedLiteralTable = makeHuffmanTable(bitLengths);
function makeHuffmanTable(bitLengths) {
  var maxBits = Math.max.apply(null, bitLengths);
  var numLengths = bitLengths.length;
  var size = 1 << maxBits;
  var codes = new Uint32Array(size);
  for (var code = 0, len = 1, skip = 2; len <= maxBits; code <<= 1, ++len, skip <<= 1) {
    for (var val = 0; val < numLengths; ++val) {
      if (bitLengths[val] === len) {
        var lsb = 0;
        for (var i = 0; i < len; ++i)
          lsb = lsb * 2 + (code >> i & 1);
        for (var i = lsb; i < size; i += skip)
          codes[i] = len << 16 | val;
        ++code;
      }
    }
  }
  return {
    codes: codes,
    maxBits: maxBits
  };
}
function verifyDeflateHeader(bytes) {
  var header = bytes[0] << 8 | bytes[1];
}
function createInflatedStream(bytes, outputLength) {
  verifyDeflateHeader(bytes);
  var stream = new Stream(bytes, 2);
  var output = {
      data: new Uint8Array(outputLength),
      available: 0,
      completed: false
    };
  var state = {
      header: null,
      distanceTable: null,
      literalTable: null,
      sym: null,
      len: null,
      sym2: null
    };
  do {
    inflateBlock(stream, output, state);
  } while (!output.completed && stream.pos < stream.end);
  return new Stream(output.data, 0, output.available);
}
var InflateNoDataError = {};
function inflateBlock(stream, output, state) {
  var header = state.header !== null ? state.header : state.header = readBits(stream.bytes, stream, 3);
  switch (header >> 1) {
  case 0:
    stream.align();
    var pos = stream.pos;
    if (stream.end - pos < 4) {
      throw InflateNoDataError;
    }
    var len = stream.getUint16(pos, true);
    var nlen = stream.getUint16(pos + 2, true);
    if (stream.end - pos < 4 + len) {
      throw InflateNoDataError;
    }
    var begin = pos + 4;
    var end = stream.pos = begin + len;
    var sbytes = stream.bytes, dbytes = output.data;
    dbytes.set(sbytes.subarray(begin, end), output.available);
    output.available += len;
    break;
  case 1:
    inflate(stream, output, fixedLiteralTable, fixedDistanceTable, state);
    break;
  case 2:
    var distanceTable, literalTable;
    if (state.distanceTable !== null) {
      distanceTable = state.distanceTable;
      literalTable = state.literalTable;
    } else {
      var sbytes = stream.bytes;
      var savedBufferPos = stream.pos;
      var savedBitBuffer = stream.bitBuffer;
      var savedBitLength = stream.bitLength;
      var bitLengths = [];
      var numLiteralCodes, numDistanceCodes;
      try {
        numLiteralCodes = readBits(sbytes, stream, 5) + 257;
        numDistanceCodes = readBits(sbytes, stream, 5) + 1;
        var numCodes = numLiteralCodes + numDistanceCodes;
        var numLengthCodes = readBits(sbytes, stream, 4) + 4;
        for (var i = 0; i < 19; ++i)
          bitLengths[codeLengthOrder[i]] = i < numLengthCodes ? readBits(sbytes, stream, 3) : 0;
        var codeLengthTable = makeHuffmanTable(bitLengths);
        bitLengths = [];
        var i = 0;
        var prev = 0;
        while (i < numCodes) {
          var j = 1;
          var sym = readCode(sbytes, stream, codeLengthTable);
          switch (sym) {
          case 16:
            j = readBits(sbytes, stream, 2) + 3;
            sym = prev;
            break;
          case 17:
            j = readBits(sbytes, stream, 3) + 3;
            sym = 0;
            break;
          case 18:
            j = readBits(sbytes, stream, 7) + 11;
            sym = 0;
            break;
          default:
            prev = sym;
          }
          while (j--)
            bitLengths[i++] = sym;
        }
      } catch (e) {
        stream.pos = savedBufferPos;
        stream.bitBuffer = savedBitBuffer;
        stream.bitLength = savedBitLength;
        throw e;
      }
      distanceTable = state.distanceTable = makeHuffmanTable(bitLengths.splice(numLiteralCodes, numDistanceCodes));
      literalTable = state.literalTable = makeHuffmanTable(bitLengths);
    }
    inflate(stream, output, literalTable, distanceTable, state);
    state.distanceTable = null;
    state.literalTable = null;
    break;
  default:
    fail('unknown block type', 'inflate');
  }
  state.header = null;
  output.completed = !(!(header & 1));
}
function readBits(bytes, stream, size) {
  var bitBuffer = stream.bitBuffer;
  var bitLength = stream.bitLength;
  if (size > bitLength) {
    var pos = stream.pos;
    var end = stream.end;
    do {
      if (pos >= end) {
        stream.pos = pos;
        stream.bitBuffer = bitBuffer;
        stream.bitLength = bitLength;
        throw InflateNoDataError;
      }
      bitBuffer |= bytes[pos++] << bitLength;
      bitLength += 8;
    } while (size > bitLength);
    stream.pos = pos;
  }
  stream.bitBuffer = bitBuffer >>> size;
  stream.bitLength = bitLength - size;
  return bitBuffer & (1 << size) - 1;
}
function inflate(stream, output, literalTable, distanceTable, state) {
  var pos = output.available;
  var dbytes = output.data;
  var sbytes = stream.bytes;
  var sym = state.sym !== null ? state.sym : readCode(sbytes, stream, literalTable);
  while (sym !== 256) {
    if (sym < 256) {
      dbytes[pos++] = sym;
    } else {
      state.sym = sym;
      sym -= 257;
      var len = state.len !== null ? state.len : state.len = lengthCodes[sym] + readBits(sbytes, stream, lengthExtraBits[sym]);
      var sym2 = state.sym2 !== null ? state.sym2 : state.sym2 = readCode(sbytes, stream, distanceTable);
      var distance = distanceCodes[sym2] + readBits(sbytes, stream, distanceExtraBits[sym2]);
      var i = pos - distance;
      while (len--)
        dbytes[pos++] = dbytes[i++];
      state.sym2 = null;
      state.len = null;
      state.sym = null;
    }
    output.available = pos;
    sym = readCode(sbytes, stream, literalTable);
  }
}
function readCode(bytes, stream, codeTable) {
  var bitBuffer = stream.bitBuffer;
  var bitLength = stream.bitLength;
  var maxBits = codeTable.maxBits;
  if (maxBits > bitLength) {
    var pos = stream.pos;
    var end = stream.end;
    do {
      if (pos >= end) {
        stream.pos = pos;
        stream.bitBuffer = bitBuffer;
        stream.bitLength = bitLength;
        throw InflateNoDataError;
      }
      bitBuffer |= bytes[pos++] << bitLength;
      bitLength += 8;
    } while (maxBits > bitLength);
    stream.pos = pos;
  }
  var code = codeTable.codes[bitBuffer & (1 << maxBits) - 1];
  var len = code >> 16;
  stream.bitBuffer = bitBuffer >>> len;
  stream.bitLength = bitLength - len;
  return code & 65535;
}
var StreamNoDataError = {};
var Stream = function StreamClosure() {
    function Stream_align() {
      this.bitBuffer = this.bitLength = 0;
    }
    function Stream_ensure(size) {
      if (this.pos + size > this.end) {
        throw StreamNoDataError;
      }
    }
    function Stream_remaining() {
      return this.end - this.pos;
    }
    function Stream_substream(begin, end) {
      var stream = new Stream(this.bytes);
      stream.pos = begin;
      stream.end = end;
      return stream;
    }
    function Stream_push(data) {
      var bytes = this.bytes;
      var newBytesLength = this.end + data.length;
      if (newBytesLength > bytes.length) {
        throw 'stream buffer overfow';
      }
      bytes.set(data, this.end);
      this.end = newBytesLength;
    }
    function Stream(buffer, offset, length, maxLength) {
      if (offset === undefined)
        offset = 0;
      if (buffer.buffer instanceof ArrayBuffer) {
        offset += buffer.byteOffset;
        buffer = buffer.buffer;
      }
      if (length === undefined)
        length = buffer.byteLength - offset;
      if (maxLength === undefined)
        maxLength = length;
      var bytes = new Uint8Array(buffer, offset, maxLength);
      var stream = new DataView(buffer, offset, maxLength);
      stream.bytes = bytes;
      stream.pos = 0;
      stream.end = length;
      stream.bitBuffer = 0;
      stream.bitLength = 0;
      stream.align = Stream_align;
      stream.ensure = Stream_ensure;
      stream.remaining = Stream_remaining;
      stream.substream = Stream_substream;
      stream.push = Stream_push;
      return stream;
    }
    return Stream;
  }();
var FORMAT_COLORMAPPED = 3;
var FORMAT_15BPP = 4;
var FORMAT_24BPP = 5;
var FACTOR_5BBP = 255 / 31;
var crcTable = [];
for (var i = 0; i < 256; i++) {
  var c = i;
  for (var h = 0; h < 8; h++) {
    if (c & 1)
      c = 3988292384 ^ c >> 1 & 2147483647;
    else
      c = c >> 1 & 2147483647;
  }
  crcTable[i] = c;
}
function crc32(data, start, end) {
  var crc = -1;
  for (var i = start; i < end; i++) {
    var a = (crc ^ data[i]) & 255;
    var b = crcTable[a];
    crc = crc >>> 8 ^ b;
  }
  return crc ^ -1;
}
function createPngChunk(type, data) {
  var chunk = new Uint8Array(12 + data.length);
  var p = 0;
  var len = data.length;
  chunk[p] = len >> 24 & 255;
  chunk[p + 1] = len >> 16 & 255;
  chunk[p + 2] = len >> 8 & 255;
  chunk[p + 3] = len & 255;
  chunk[p + 4] = type.charCodeAt(0) & 255;
  chunk[p + 5] = type.charCodeAt(1) & 255;
  chunk[p + 6] = type.charCodeAt(2) & 255;
  chunk[p + 7] = type.charCodeAt(3) & 255;
  if (data instanceof Uint8Array)
    chunk.set(data, 8);
  p = 8 + len;
  var crc = crc32(chunk, 4, p);
  chunk[p] = crc >> 24 & 255;
  chunk[p + 1] = crc >> 16 & 255;
  chunk[p + 2] = crc >> 8 & 255;
  chunk[p + 3] = crc & 255;
  return chunk;
}
function adler32(data, start, end) {
  var a = 1;
  var b = 0;
  for (var i = start; i < end; ++i) {
    a = (a + (data[i] & 255)) % 65521;
    b = (b + a) % 65521;
  }
  return b << 16 | a;
}
function defineBitmap(tag) {
  var width = tag.width;
  var height = tag.height;
  var hasAlpha = tag.hasAlpha;
  var plte = '';
  var trns = '';
  var literals;
  var bmpData = tag.bmpData;
  switch (tag.format) {
  case FORMAT_COLORMAPPED:
    var colorType = 3;
    var bytesPerLine = width + 3 & ~3;
    var colorTableSize = tag.colorTableSize + 1;
    var paletteSize = colorTableSize * (tag.hasAlpha ? 4 : 3);
    var datalen = paletteSize + bytesPerLine * height;
    var stream = createInflatedStream(bmpData, datalen);
    var bytes = stream.bytes;
    var pos = 0;
    stream.ensure(paletteSize);
    if (hasAlpha) {
      var palette = new Uint8Array(paletteSize / 4 * 3);
      var pp = 0;
      var alphaValues = new Uint8Array(paletteSize / 4);
      var pa = 0;
      while (pos < paletteSize) {
        palette[pp++] = bytes[pos];
        palette[pp++] = bytes[pos + 1];
        palette[pp++] = bytes[pos + 2];
        alphaValues[pa++] = bytes[pos + 3];
        pos += 4;
      }
      plte = createPngChunk('PLTE', palette);
      trns = createPngChunk('tRNS', alphaValues);
    } else {
      plte = createPngChunk('PLTE', bytes.subarray(pos, pos + paletteSize));
      pos += paletteSize;
    }
    literals = new Uint8Array(width * height + height);
    var pl = 0;
    while (pos < datalen) {
      stream.ensure(bytesPerLine);
      var begin = pos;
      var end = begin + width;
      pl++;
      literals.set(bytes.subarray(begin, end), pl);
      pl += end - begin;
      stream.pos = pos += bytesPerLine;
    }
    break;
  case FORMAT_15BPP:
    var colorType = 2;
    var bytesPerLine = width * 2 + 3 & ~3;
    var stream = createInflatedStream(bmpData, bytesPerLine * height);
    var pos = 0;
    literals = new Uint8Array(width * height * 3 + height);
    var pl = 0;
    for (var y = 0; y < height; ++y) {
      pl++;
      stream.ensure(bytesPerLine);
      for (var x = 0; x < width; ++x) {
        var word = stream.getUint16(pos);
        pos += 2;
        literals[pl++] = 0 | FACTOR_5BBP * (word >> 10 & 31);
        literals[pl++] = 0 | FACTOR_5BBP * (word >> 5 & 31);
        literals[pl++] = 0 | FACTOR_5BBP * (word & 31);
      }
      stream.pos = pos += bytesPerLine;
    }
    break;
  case FORMAT_24BPP:
    var padding;
    if (hasAlpha) {
      var colorType = 6;
      padding = 0;
      literals = new Uint8Array(width * height * 4 + height);
    } else {
      var colorType = 2;
      padding = 1;
      literals = new Uint8Array(width * height * 3 + height);
    }
    var bytesPerLine = width * 4;
    var stream = createInflatedStream(bmpData, bytesPerLine * height);
    var bytes = stream.bytes;
    var pos = 0;
    var pl = 0;
    for (var y = 0; y < height; ++y) {
      stream.ensure(bytesPerLine);
      pl++;
      for (var x = 0; x < width; ++x) {
        pos += padding;
        if (hasAlpha) {
          var alpha = bytes[pos];
          if (alpha) {
            var opacity = alpha / 255;
            literals[pl++] = 0 | bytes[pos + 1] / opacity;
            literals[pl++] = 0 | bytes[pos + 2] / opacity;
            literals[pl++] = 0 | bytes[pos + 3] / opacity;
            literals[pl++] = alpha;
          } else {
            pl += 4;
          }
        } else {
          literals[pl++] = bytes[pos];
          literals[pl++] = bytes[pos + 1];
          literals[pl++] = bytes[pos + 2];
        }
        pos += 4 - padding;
      }
      stream.pos = pos;
    }
    break;
  default:
    fail('invalid format', 'bitmap');
  }
  var ihdr = new Uint8Array([
      width >> 24 & 255,
      width >> 16 & 255,
      width >> 8 & 255,
      width & 255,
      height >> 24 & 255,
      height >> 16 & 255,
      height >> 8 & 255,
      height & 255,
      8,
      colorType,
      0,
      0,
      0
    ]);
  var len = literals.length;
  var maxBlockLength = 65535;
  var idat = new Uint8Array(2 + len + Math.ceil(len / maxBlockLength) * 5 + 4);
  var pi = 0;
  idat[pi++] = 120;
  idat[pi++] = 156;
  var pos = 0;
  while (len > maxBlockLength) {
    idat[pi++] = 0;
    idat[pi++] = 255;
    idat[pi++] = 255;
    idat[pi++] = 0;
    idat[pi++] = 0;
    idat.set(literals.subarray(pos, pos + maxBlockLength), pi);
    pi += maxBlockLength;
    pos += maxBlockLength;
    len -= maxBlockLength;
  }
  idat[pi++] = 1;
  idat[pi++] = len & 255;
  idat[pi++] = len >> 8 & 255;
  idat[pi++] = ~len & 65535 & 255;
  idat[pi++] = (~len & 65535) >> 8 & 255;
  idat.set(literals.subarray(pos), pi);
  pi += literals.length - pos;
  var adler = adler32(literals, 0, literals.length);
  idat[pi++] = adler >> 24 & 255;
  idat[pi++] = adler >> 16 & 255;
  idat[pi++] = adler >> 8 & 255;
  idat[pi++] = adler & 255;
  var chunks = [
      new Uint8Array([
        137,
        80,
        78,
        71,
        13,
        10,
        26,
        10
      ]),
      createPngChunk('IHDR', ihdr),
      plte,
      trns,
      createPngChunk('IDAT', idat),
      createPngChunk('IEND', '')
    ];
  return {
    type: 'image',
    id: tag.id,
    width: width,
    height: height,
    mimeType: 'image/png',
    data: new Blob(chunks, {
      type: 'image/png'
    })
  };
}
function defineButton(tag, dictionary) {
  var characters = tag.characters;
  var states = {
      up: {},
      over: {},
      down: {},
      hitTest: {}
    };
  var i = 0, character;
  while (character = characters[i++]) {
    if (character.eob)
      break;
    var characterItem = dictionary[character.symbolId];
    var entry = {
        symbolId: characterItem.id,
        hasMatrix: !(!character.matrix),
        matrix: character.matrix
      };
    if (character.stateUp)
      states.up[character.depth] = entry;
    if (character.stateOver)
      states.over[character.depth] = entry;
    if (character.stateDown)
      states.down[character.depth] = entry;
    if (character.stateHitTest)
      states.hitTest[character.depth] = entry;
  }
  var button = {
      type: 'button',
      id: tag.id,
      buttonActions: tag.buttonActions,
      states: states
    };
  return button;
}
var nextFontId = 1;
function maxPower2(num) {
  var maxPower = 0;
  var val = num;
  while (val >= 2) {
    val /= 2;
    ++maxPower;
  }
  return pow(2, maxPower);
}
function toString16(val) {
  return fromCharCode(val >> 8 & 255, val & 255);
}
function toString32(val) {
  return toString16(val >> 16) + toString16(val);
}
function defineFont(tag, dictionary) {
  var tables = {};
  var codes = [];
  var glyphIndex = {};
  var ranges = [];
  var glyphs = tag.glyphs;
  var glyphCount = glyphs.length;
  if (tag.codes) {
    codes = codes.concat(tag.codes);
    for (var i = 0, code; code = codes[i]; ++i)
      glyphIndex[code] = i;
    codes.sort(function (a, b) {
      return a - b;
    });
    var i = 0;
    var code;
    while (code = codes[i++]) {
      var start = code;
      var end = start;
      var indices = [
          i - 1
        ];
      while ((code = codes[i]) && end + 1 === code) {
        ++end;
        indices.push(i);
        ++i;
      }
      ranges.push([
        start,
        end,
        indices
      ]);
    }
  } else {
    var indices = [];
    var UAC_OFFSET = 57344;
    for (var i = 0; i < glyphCount; i++) {
      var code = UAC_OFFSET + i;
      codes.push(code);
      glyphIndex[code] = i;
      indices.push(i);
    }
    ranges.push([
      UAC_OFFSET,
      UAC_OFFSET + glyphCount - 1,
      indices
    ]);
  }
  var resolution = tag.resolution || 1;
  var ascent = Math.ceil(tag.ascent / resolution) || 1024;
  var descent = -Math.ceil(tag.descent / resolution) | 0;
  var leading = tag.leading / resolution | 0;
  tables['OS/2'] = '\0\x01\0\0' + toString16(tag.bold ? 700 : 400) + '\0\x05' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0\0\0\0\0\0\0\0\0' + '\0\0\0\0' + '\0\0\0\0' + '\0\0\0\0' + '\0\0\0\0' + 'ALF ' + toString16((tag.italic ? 1 : 0) | (tag.bold ? 32 : 0)) + toString16(codes[0]) + toString16(codes[codes.length - 1]) + toString16(ascent) + toString16(descent) + toString16(leading) + toString16(ascent) + toString16(-descent) + '\0\0\0\0' + '\0\0\0\0';
  ;
  var startCount = '';
  var endCount = '';
  var idDelta = '';
  var idRangeOffset = '';
  var i = 0;
  var range;
  while (range = ranges[i++]) {
    var start = range[0];
    var end = range[1];
    var code = range[2][0];
    startCount += toString16(start);
    endCount += toString16(end);
    idDelta += toString16(code - start + 1 & 65535);
    idRangeOffset += toString16(0);
  }
  endCount += '\xff\xff';
  startCount += '\xff\xff';
  idDelta += '\0\x01';
  idRangeOffset += '\0\0';
  var segCount = ranges.length + 1;
  var searchRange = maxPower2(segCount) * 2;
  var rangeShift = 2 * segCount - searchRange;
  var format314 = '\0\0' + toString16(segCount * 2) + toString16(searchRange) + toString16(logE(segCount) / logE(2)) + toString16(rangeShift) + endCount + '\0\0' + startCount + idDelta + idRangeOffset;
  ;
  tables['cmap'] = '\0\0\0\x01\0\x03\0\x01\0\0\0\f\0\x04' + toString16(format314.length + 4) + format314;
  ;
  var glyf = '\0\x01\0\0\0\0\0\0\0\0\0\0\0\x001\0';
  var loca = '\0\0';
  var offset = 16;
  var maxPoints = 0;
  var xMins = [];
  var xMaxs = [];
  var yMins = [];
  var yMaxs = [];
  var maxContours = 0;
  var i = 0;
  var code;
  while (code = codes[i++]) {
    var glyph = glyphs[glyphIndex[code]];
    var records = glyph.records;
    var numberOfContours = 1;
    var endPoint = 0;
    var endPtsOfContours = '';
    var flags = '';
    var xCoordinates = '';
    var yCoordinates = '';
    var x = 0;
    var y = 0;
    var xMin = 1024;
    var xMax = -1024;
    var yMin = 1024;
    var yMax = -1024;
    for (var j = 0, record; record = records[j]; ++j) {
      if (record.type) {
        if (record.isStraight) {
          if (record.isGeneral) {
            flags += '\x01';
            var dx = record.deltaX / resolution;
            var dy = -record.deltaY / resolution;
            xCoordinates += toString16(dx);
            yCoordinates += toString16(dy);
            x += dx;
            y += dy;
          } else if (record.isVertical) {
            flags += '\x11';
            var dy = -record.deltaY / resolution;
            yCoordinates += toString16(dy);
            y += dy;
          } else {
            flags += '!';
            var dx = record.deltaX / resolution;
            xCoordinates += toString16(dx);
            x += dx;
          }
        } else {
          flags += '\0';
          var cx = record.controlDeltaX / resolution;
          var cy = -record.controlDeltaY / resolution;
          xCoordinates += toString16(cx);
          yCoordinates += toString16(cy);
          flags += '\x01';
          var dx = record.anchorDeltaX / resolution;
          var dy = -record.anchorDeltaY / resolution;
          xCoordinates += toString16(dx);
          yCoordinates += toString16(dy);
          ++endPoint;
          x += cx + dx;
          y += cy + dy;
        }
        if (x < xMin)
          xMin = x;
        if (x > xMax)
          xMax = x;
        if (y < yMin)
          yMin = y;
        if (y > yMax)
          yMax = y;
        ++endPoint;
      } else {
        if (record.eos)
          break;
        if (record.move) {
          if (endPoint) {
            ++numberOfContours;
            endPtsOfContours += toString16(endPoint - 1);
          }
          flags += '\x01';
          var moveX = record.moveX / resolution;
          var moveY = -record.moveY / resolution;
          var dx = moveX - x;
          var dy = moveY - y;
          xCoordinates += toString16(dx);
          yCoordinates += toString16(dy);
          x = moveX;
          y = moveY;
          if (endPoint > maxPoints)
            maxPoints = endPoint;
          if (x < xMin)
            xMin = x;
          if (x > xMax)
            xMax = x;
          if (y < yMin)
            yMin = y;
          if (y > yMax)
            yMax = y;
          ++endPoint;
        }
      }
    }
    endPtsOfContours += toString16((endPoint || 1) - 1);
    if (!j) {
      xMin = xMax = yMin = yMax = 0;
      flags += '1';
    }
    var entry = toString16(numberOfContours) + toString16(xMin) + toString16(yMin) + toString16(xMax) + toString16(yMax) + endPtsOfContours + '\0\0' + flags + xCoordinates + yCoordinates;
    ;
    if (entry.length & 1)
      entry += '\0';
    glyf += entry;
    loca += toString16(offset / 2);
    offset += entry.length;
    xMins.push(xMin);
    xMaxs.push(xMax);
    yMins.push(yMin);
    yMaxs.push(yMax);
    if (numberOfContours > maxContours)
      maxContours = numberOfContours;
    if (endPoint > maxPoints)
      maxPoints = endPoint;
  }
  loca += toString16(offset / 2);
  tables['glyf'] = glyf;
  tables['head'] = '\0\x01\0\0\0\x01\0\0\0\0\0\0_\x0f<\xf5\0\v\x04\0\0\0\0\0' + toString32(Date.now()) + '\0\0\0\0' + toString32(Date.now()) + toString16(min.apply(null, xMins)) + toString16(min.apply(null, yMins)) + toString16(max.apply(null, xMaxs)) + toString16(max.apply(null, yMaxs)) + toString16((tag.italic ? 2 : 0) | (tag.bold ? 1 : 0)) + '\0\b' + '\0\x02' + '\0\0' + '\0\0';
  ;
  var advance = tag.advance;
  tables['hhea'] = '\0\x01\0\0' + toString16(ascent) + toString16(descent) + toString16(leading) + toString16(advance ? max.apply(null, advance) : 1024) + '\0\0' + '\0\0' + '\x03\xb8' + '\0\x01' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + toString16(glyphCount + 1);
  ;
  var hmtx = '\0\0\0\0';
  for (var i = 0; i < glyphCount; ++i)
    hmtx += toString16(advance ? advance[i] / resolution : 1024) + '\0\0';
  tables['hmtx'] = hmtx;
  if (tag.kerning) {
    var kerning = tag.kerning;
    var nPairs = kerning.length;
    var searchRange = maxPower2(nPairs) * 2;
    var kern = '\0\0\0\x01\0\0' + toString16(14 + nPairs * 6) + '\0\x01' + toString16(nPairs) + toString16(searchRange) + toString16(logE(nPairs) / logE(2)) + toString16(2 * nPairs - searchRange);
    ;
    var i = 0;
    var record;
    while (record = kerning[i++]) {
      kern += toString16(glyphIndex[record.code1]) + toString16(glyphIndex[record.code2]) + toString16(record.adjustment);
      ;
    }
    tables['kern'] = kern;
  }
  tables['loca'] = loca;
  tables['maxp'] = '\0\x01\0\0' + toString16(glyphCount + 1) + toString16(maxPoints) + toString16(maxContours) + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0';
  ;
  var uniqueId = 'swf-font-' + nextFontId++;
  var fontName = tag.name || uniqueId;
  var psName = fontName.replace(/ /g, '');
  var strings = [
      tag.copyright || 'Original licence',
      fontName,
      'Unknown',
      uniqueId,
      fontName,
      '1.0',
      psName,
      'Unknown',
      'Unknown',
      'Unknown'
    ];
  var count = strings.length;
  var name = '\0\0' + toString16(count) + toString16(count * 12 + 6);
  var offset = 0;
  var i = 0;
  var str;
  while (str = strings[i++]) {
    name += '\0\x01\0\0\0\0' + toString16(i - 1) + toString16(str.length) + toString16(offset);
    offset += str.length;
  }
  tables['name'] = name + strings.join('');
  tables['post'] = '\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0';
  ;
  var names = keys(tables);
  var numTables = names.length;
  var header = '\0\x01\0\0' + toString16(numTables) + '\0\x80' + '\0\x03' + '\0 ';
  ;
  var data = '';
  var offset = numTables * 16 + header.length;
  var i = 0;
  var name;
  while (name = names[i++]) {
    var table = tables[name];
    var length = table.length;
    header += name + '\0\0\0\0' + toString32(offset) + toString32(length);
    ;
    while (length & 3) {
      table += '\0';
      ++length;
    }
    data += table;
    while (offset & 3)
      ++offset;
    offset += length;
  }
  var otf = header + data;
  var unitPerEm = 1024;
  var metrics = {
      ascent: ascent / unitPerEm,
      descent: -descent / unitPerEm,
      leading: leading / unitPerEm
    };
  return {
    type: 'font',
    id: tag.id,
    name: fontName,
    uniqueName: psName + uniqueId,
    codes: codes,
    metrics: metrics,
    bold: tag.bold === 1,
    italic: tag.italic === 1,
    data: otf
  };
}
function getUint16(buff, pos) {
  return buff[pos] << 8 | buff[pos + 1];
}
function parseJpegChunks(imgDef, bytes) {
  var i = 0;
  var n = bytes.length;
  var chunks = [];
  var code;
  do {
    var begin = i;
    while (i < n && bytes[i] !== 255)
      ++i;
    while (i < n && bytes[i] === 255)
      ++i;
    code = bytes[i++];
    if (code === 218) {
      i = n;
    } else if (code === 217) {
      i += 2;
      continue;
    } else if (code < 208 || code > 216) {
      var length = getUint16(bytes, i);
      if (code >= 192 && code <= 195) {
        imgDef.height = getUint16(bytes, i + 3);
        imgDef.width = getUint16(bytes, i + 5);
      }
      i += length;
    }
    chunks.push(bytes.subarray(begin, i));
  } while (i < n);
  return chunks;
}
function defineImage(tag, dictionary) {
  var img = {
      type: 'image',
      id: tag.id,
      mimeType: tag.mimeType
    };
  var imgData = tag.imgData;
  var chunks;
  if (tag.mimeType === 'image/jpeg') {
    chunks = parseJpegChunks(img, imgData);
    var alphaData = tag.alphaData;
    if (alphaData) {
      img.mask = createInflatedStream(alphaData, img.width * img.height).bytes;
    }
    if (tag.incomplete) {
      var tables = dictionary[0];
      var header = tables.data;
      if (header && header.size) {
        chunks[0] = chunks[0].subarray(2);
        chunks.unshift(header.slice(0, header.size - 2));
      }
    }
  } else {
    chunks = [
      imgData
    ];
  }
  img.data = new Blob(chunks, {
    type: tag.mimeType
  });
  return img;
}
function defineLabel(tag, dictionary) {
  var records = tag.records;
  var m = tag.matrix;
  var cmds = [
      'c.save()',
      'c.transform(' + [
        m.a,
        m.b,
        m.c,
        m.d,
        m.tx / 20,
        m.ty / 20
      ].join(',') + ')',
      'c.scale(0.05, 0.05)'
    ];
  var dependencies = [];
  var x = 0;
  var y = 0;
  var i = 0;
  var record;
  var codes;
  while (record = records[i++]) {
    if (record.eot)
      break;
    if (record.hasFont) {
      var font = dictionary[record.fontId];
      codes = font.codes;
      cmds.push('c.font="' + record.fontHeight + 'px \'' + font.uniqueName + '\'"');
      dependencies.push(font.id);
    }
    if (record.hasColor) {
      cmds.push('ct.setFillStyle(c,"' + rgbaObjToStr(record.color) + '")');
      cmds.push('ct.setAlpha(c)');
    } else {
      cmds.push('ct.setAlpha(c,true)');
    }
    if (record.hasMoveX)
      x = record.moveX;
    if (record.hasMoveY)
      y = record.moveY;
    var entries = record.entries;
    var j = 0;
    var entry;
    while (entry = entries[j++]) {
      var code = codes[entry.glyphIndex];
      var text = code >= 32 && code != 34 && code != 92 ? fromCharCode(code) : '\\u' + (code + 65536).toString(16).substring(1);
      cmds.push('c.fillText("' + text + '",' + x + ',' + y + ')');
      x += entry.advance;
    }
  }
  cmds.push('c.restore()');
  var label = {
      type: 'label',
      id: tag.id,
      bbox: tag.bbox,
      data: cmds.join('\n')
    };
  if (dependencies.length)
    label.require = dependencies;
  return label;
}
var GRAPHICS_FILL_CLIPPED_BITMAP = 65;
var GRAPHICS_FILL_FOCAL_RADIAL_GRADIENT = 19;
var GRAPHICS_FILL_LINEAR_GRADIENT = 16;
var GRAPHICS_FILL_NONSMOOTHED_CLIPPED_BITMAP = 67;
var GRAPHICS_FILL_NONSMOOTHED_REPEATING_BITMAP = 66;
var GRAPHICS_FILL_RADIAL_GRADIENT = 18;
var GRAPHICS_FILL_REPEATING_BITMAP = 64;
var GRAPHICS_FILL_SOLID = 0;
function applySegmentToStyles(segment, styles, linePaths, fillPaths, isMorph) {
  if (!segment) {
    return;
  }
  var commands = segment.commands;
  var data = segment.data;
  var morphData = segment.morphData;
  if (morphData) {
  }
  var path;
  var targetSegment;
  var command;
  var i;
  if (styles.fill0) {
    path = fillPaths[styles.fill0 - 1];
    if (!(styles.fill1 || styles.line)) {
      targetSegment = path.head();
      targetSegment.commands = [];
      targetSegment.data = [];
      targetSegment.morphData = isMorph ? [] : null;
    } else {
      targetSegment = path.addSegment([], [], isMorph ? [] : null);
    }
    var targetCommands = targetSegment.commands;
    var targetData = targetSegment.data;
    var targetMorphData = targetSegment.morphData;
    targetCommands.push(SHAPE_MOVE_TO);
    var j = data.length - 2;
    targetData.push(data[j], data[j + 1]);
    if (isMorph) {
      targetMorphData.push(morphData[j], morphData[j + 1]);
    }
    for (i = commands.length; i-- > 1; j -= 2) {
      command = commands[i];
      targetCommands.push(command);
      targetData.push(data[j - 2], data[j - 1]);
      if (isMorph) {
        targetMorphData.push(morphData[j - 2], morphData[j - 1]);
      }
      if (command === SHAPE_CURVE_TO) {
        targetData.push(data[j - 4], data[j - 3]);
        if (isMorph) {
          targetMorphData.push(morphData[j - 4], morphData[j - 3]);
        }
        j -= 2;
      }
    }
    if (isMorph) {
    }
  }
  if (styles.line && styles.fill1) {
    path = linePaths[styles.line - 1];
    path.addSegment(commands, data, morphData);
  }
}
function convertRecordsToStyledPaths(records, fillPaths, linePaths, dictionary, dependencies, recordsMorph, transferables) {
  var isMorph = recordsMorph !== null;
  var styles = {
      fill0: 0,
      fill1: 0,
      line: 0
    };
  var segment = null;
  var allPaths;
  var defaultPath;
  var numRecords = records.length - 1;
  var x = 0;
  var y = 0;
  var morphX = 0;
  var morphY = 0;
  var path;
  for (var i = 0, j = 0; i < numRecords; i++) {
    var record = records[i];
    var morphRecord;
    if (isMorph) {
      morphRecord = recordsMorph[j++];
    }
    if (record.type === 0) {
      if (segment) {
        applySegmentToStyles(segment, styles, linePaths, fillPaths, isMorph);
      }
      if (record.hasNewStyles) {
        if (!allPaths) {
          allPaths = [];
        }
        push.apply(allPaths, fillPaths);
        fillPaths = createPathsList(record.fillStyles, false, dictionary, dependencies);
        push.apply(allPaths, linePaths);
        linePaths = createPathsList(record.lineStyles, true, dictionary, dependencies);
        if (defaultPath) {
          allPaths.push(defaultPath);
          defaultPath = null;
        }
        styles = {
          fill0: 0,
          fill1: 0,
          line: 0
        };
      }
      if (record.hasFillStyle0) {
        styles.fill0 = record.fillStyle0;
      }
      if (record.hasFillStyle1) {
        styles.fill1 = record.fillStyle1;
      }
      if (record.hasLineStyle) {
        styles.line = record.lineStyle;
      }
      if (styles.fill1) {
        path = fillPaths[styles.fill1 - 1];
      } else if (styles.line) {
        path = linePaths[styles.line - 1];
      } else if (styles.fill0) {
        path = fillPaths[styles.fill0 - 1];
      }
      if (record.move) {
        x = record.moveX | 0;
        y = record.moveY | 0;
      }
      if (path) {
        segment = path.addSegment([], [], isMorph ? [] : null);
        segment.commands.push(SHAPE_MOVE_TO);
        segment.data.push(x, y);
        if (isMorph) {
          if (morphRecord.type === 0) {
            morphX = morphRecord.moveX | 0;
            morphY = morphRecord.moveY | 0;
          } else {
            morphX = x;
            morphY = y;
            j--;
          }
          segment.morphData.push(morphX, morphY);
        }
      }
    } else {
      if (!segment) {
        if (!defaultPath) {
          var style = {
              color: {
                red: 0,
                green: 0,
                blue: 0,
                alpha: 255
              },
              width: 20
            };
          defaultPath = new SegmentedPath(null, processStyle(style, true));
        }
        segment = defaultPath.addSegment([], [], isMorph ? [] : null);
        segment.commands.push(SHAPE_MOVE_TO);
        segment.data.push(x, y);
        if (isMorph) {
          segment.morphData.push(morphX, morphY);
        }
      }
      if (isMorph) {
        while (morphRecord && morphRecord.type === 0) {
          morphRecord = recordsMorph[j++];
        }
        if (!morphRecord) {
          morphRecord = record;
        }
      }
      if (record.isStraight && (!isMorph || morphRecord.isStraight)) {
        x += record.deltaX | 0;
        y += record.deltaY | 0;
        segment.commands.push(SHAPE_LINE_TO);
        segment.data.push(x, y);
        if (isMorph) {
          morphX += morphRecord.deltaX | 0;
          morphY += morphRecord.deltaY | 0;
          segment.morphData.push(morphX, morphY);
        }
      } else {
        var cx, cy;
        var deltaX, deltaY;
        if (!record.isStraight) {
          cx = x + record.controlDeltaX | 0;
          cy = y + record.controlDeltaY | 0;
          x = cx + record.anchorDeltaX | 0;
          y = cy + record.anchorDeltaY | 0;
        } else {
          deltaX = record.deltaX | 0;
          deltaY = record.deltaY | 0;
          cx = x + (deltaX >> 1);
          cy = y + (deltaY >> 1);
          x += deltaX;
          y += deltaY;
        }
        segment.commands.push(SHAPE_CURVE_TO);
        segment.data.push(cx, cy, x, y);
        if (isMorph) {
          if (!morphRecord.isStraight) {
            cx = morphX + morphRecord.controlDeltaX | 0;
            cy = morphY + morphRecord.controlDeltaY | 0;
            morphX = cx + morphRecord.anchorDeltaX | 0;
            morphY = cy + morphRecord.anchorDeltaY | 0;
          } else {
            deltaX = morphRecord.deltaX | 0;
            deltaY = morphRecord.deltaY | 0;
            cx = morphX + (deltaX >> 1);
            cy = morphY + (deltaY >> 1);
            morphX += deltaX;
            morphY += deltaY;
          }
          segment.morphData.push(cx, cy, morphX, morphY);
        }
      }
    }
  }
  applySegmentToStyles(segment, styles, linePaths, fillPaths, isMorph);
  if (allPaths) {
    push.apply(allPaths, fillPaths);
  } else {
    allPaths = fillPaths;
  }
  push.apply(allPaths, linePaths);
  if (defaultPath) {
    allPaths.push(defaultPath);
  }
  var removeCount = 0;
  for (i = 0; i < allPaths.length; i++) {
    path = allPaths[i];
    if (!path.head()) {
      removeCount++;
      continue;
    }
    allPaths[i - removeCount] = segmentedPathToShapePath(path, isMorph, transferables);
  }
  allPaths.length -= removeCount;
  return allPaths;
}
function segmentedPathToShapePath(path, isMorph, transferables) {
  var start = path.head();
  var end = start;
  var finalRoot = null;
  var finalHead = null;
  var skippedMoves = 0;
  var current = start.prev;
  while (start) {
    while (current) {
      if (path.segmentsConnect(current, start)) {
        if (current.next !== start) {
          path.removeSegment(current);
          path.insertSegment(current, start);
        }
        start = current;
        current = start.prev;
        skippedMoves++;
        continue;
      }
      if (path.segmentsConnect(end, current)) {
        path.removeSegment(current);
        end.next = current;
        current = current.prev;
        end.next.prev = end;
        end.next.next = null;
        end = end.next;
        skippedMoves++;
        continue;
      }
      current = current.prev;
    }
    current = start.prev;
    if (!finalRoot) {
      finalRoot = start;
      finalHead = end;
    } else {
      finalHead.next = start;
      start.prev = finalHead;
      finalHead = end;
      finalHead.next = null;
    }
    if (!current) {
      break;
    }
    start = end = current;
    current = start.prev;
  }
  var totalCommandsLength = -skippedMoves;
  var totalDataLength = -skippedMoves << 1;
  current = finalRoot;
  while (current) {
    totalCommandsLength += current.commands.length;
    totalDataLength += current.data.length;
    current = current.next;
  }
  var shape = new ShapePath(path.fillStyle, path.lineStyle, totalCommandsLength, totalDataLength, isMorph, transferables);
  var allCommands = shape.commands;
  var allData = shape.data;
  var allMorphData = shape.morphData;
  var commandsIndex = 0;
  var dataIndex = 0;
  current = finalRoot;
  while (current) {
    var commands = current.commands;
    var data = current.data;
    var morphData = current.morphData;
    var offset = +(data[0] === allData[dataIndex - 2] && data[1] === allData[dataIndex - 1]);
    for (var i = offset; i < commands.length; i++, commandsIndex++) {
      allCommands[commandsIndex] = commands[i];
    }
    for (i = offset << 1; i < data.length; i++, dataIndex++) {
      allData[dataIndex] = data[i];
      if (isMorph) {
        allMorphData[dataIndex] = morphData[i];
      }
    }
    current = current.next;
  }
  return shape;
}
var CAPS_STYLE_TYPES = [
    'round',
    'none',
    'square'
  ];
var JOIN_STYLE_TYPES = [
    'round',
    'bevel',
    'miter'
  ];
function processStyle(style, isLineStyle, dictionary, dependencies) {
  if (isLineStyle) {
    style.lineCap = CAPS_STYLE_TYPES[style.endCapStyle | 0];
    style.lineJoin = JOIN_STYLE_TYPES[style.joinStyle | 0];
    style.miterLimit = (style.miterLimitFactor || 1.5) * 2;
    if (!style.color && style.hasFill) {
      var fillStyle = processStyle(style.fillStyle, false, dictionary, dependencies);
      style.style = fillStyle.style;
      style.type = fillStyle.type;
      style.transform = fillStyle.transform;
      style.records = fillStyle.records;
      style.focalPoint = fillStyle.focalPoint;
      style.bitmapId = fillStyle.bitmapId;
      style.repeat = fillStyle.repeat;
      style.fillStyle = null;
      return style;
    }
  }
  var color;
  if (style.type === undefined || style.type === GRAPHICS_FILL_SOLID) {
    color = style.color;
    style.style = 'rgba(' + color.red + ',' + color.green + ',' + color.blue + ',' + color.alpha / 255 + ')';
    style.color = null;
    return style;
  }
  var scale;
  switch (style.type) {
  case GRAPHICS_FILL_LINEAR_GRADIENT:
  case GRAPHICS_FILL_RADIAL_GRADIENT:
  case GRAPHICS_FILL_FOCAL_RADIAL_GRADIENT:
    scale = 819.2;
    break;
  case GRAPHICS_FILL_REPEATING_BITMAP:
  case GRAPHICS_FILL_CLIPPED_BITMAP:
  case GRAPHICS_FILL_NONSMOOTHED_REPEATING_BITMAP:
  case GRAPHICS_FILL_NONSMOOTHED_CLIPPED_BITMAP:
    if (dictionary[style.bitmapId]) {
      dependencies.push(dictionary[style.bitmapId].id);
      scale = 0.05;
    }
    break;
  default:
    fail('invalid fill style', 'shape');
  }
  if (!style.matrix) {
    return style;
  }
  var matrix = style.matrix;
  style.transform = {
    a: matrix.a * scale,
    b: matrix.b * scale,
    c: matrix.c * scale,
    d: matrix.d * scale,
    e: matrix.tx,
    f: matrix.ty
  };
  style.matrix = null;
  return style;
}
function createPathsList(styles, isLineStyle, dictionary, dependencies) {
  var paths = [];
  for (var i = 0; i < styles.length; i++) {
    var style = processStyle(styles[i], isLineStyle, dictionary, dependencies);
    if (!isLineStyle) {
      paths[i] = new SegmentedPath(style, null);
    } else {
      paths[i] = new SegmentedPath(null, style);
    }
  }
  return paths;
}
function defineShape(tag, dictionary) {
  var dependencies = [];
  var transferables = [];
  var fillPaths = createPathsList(tag.fillStyles, false, dictionary, dependencies);
  var linePaths = createPathsList(tag.lineStyles, true, dictionary, dependencies);
  var paths = convertRecordsToStyledPaths(tag.records, fillPaths, linePaths, dictionary, dependencies, tag.recordsMorph || null, transferables);
  if (tag.bboxMorph) {
    var mbox = tag.bboxMorph;
    extendBoundsByPoint(tag.bbox, mbox.xMin, mbox.yMin);
    extendBoundsByPoint(tag.bbox, mbox.xMax, mbox.yMax);
    mbox = tag.strokeBboxMorph;
    if (mbox) {
      extendBoundsByPoint(tag.strokeBbox, mbox.xMin, mbox.yMin);
      extendBoundsByPoint(tag.strokeBbox, mbox.xMax, mbox.yMax);
    }
  }
  return {
    type: 'shape',
    id: tag.id,
    strokeBbox: tag.strokeBbox,
    strokeBboxMorph: tag.strokeBboxMorph,
    bbox: tag.bbox,
    bboxMorph: tag.bboxMorph,
    isMorph: tag.isMorph,
    paths: paths,
    require: dependencies.length ? dependencies : null,
    transferables: transferables
  };
}
function logShape(paths, bbox) {
  var output = '{"bounds":' + JSON.stringify(bbox) + ',"paths":[' + paths.map(function (path) {
      return path.serialize();
    }).join() + ']}';
  console.log(output);
}
function SegmentedPath(fillStyle, lineStyle) {
  this.fillStyle = fillStyle;
  this.lineStyle = lineStyle;
  this._head = null;
}
SegmentedPath.prototype = {
  addSegment: function (commands, data, morphData) {
    var segment = {
        commands: commands,
        data: data,
        morphData: morphData,
        prev: this._head,
        next: null
      };
    if (this._head) {
      this._head.next = segment;
    }
    this._head = segment;
    return segment;
  },
  removeSegment: function (segment) {
    if (segment.prev) {
      segment.prev.next = segment.next;
    }
    if (segment.next) {
      segment.next.prev = segment.prev;
    }
  },
  insertSegment: function (segment, next) {
    var prev = next.prev;
    segment.prev = prev;
    segment.next = next;
    if (prev) {
      prev.next = segment;
    }
    next.prev = segment;
  },
  head: function () {
    return this._head;
  },
  segmentsConnect: function (first, second) {
    var firstLength = first.data.length;
    return first.data[firstLength - 2] === second.data[0] && first.data[firstLength - 1] === second.data[1];
  }
};
var SHAPE_MOVE_TO = 1;
var SHAPE_LINE_TO = 2;
var SHAPE_CURVE_TO = 3;
var SHAPE_WIDE_MOVE_TO = 4;
var SHAPE_WIDE_LINE_TO = 5;
var SHAPE_CUBIC_CURVE_TO = 6;
var SHAPE_CIRCLE = 7;
var SHAPE_ELLIPSE = 8;
function ShapePath(fillStyle, lineStyle, commandsCount, dataLength, isMorph, transferables) {
  this.fillStyle = fillStyle;
  this.lineStyle = lineStyle;
  if (commandsCount) {
    this.commands = new Uint8Array(commandsCount);
    this.data = new Int32Array(dataLength);
    this.morphData = isMorph ? new Int32Array(dataLength) : null;
  } else {
    this.commands = [];
    this.data = [];
  }
  this.bounds = null;
  this.strokeBounds = null;
  this.isMorph = !(!isMorph);
  this.fullyInitialized = false;
  if (inWorker) {
    this.buffers = [
      this.commands.buffer,
      this.data.buffer
    ];
    transferables.push(this.commands.buffer, this.data.buffer);
    if (isMorph) {
      this.buffers.push(this.morphData.buffer);
      transferables.push(this.morphData.buffer);
    }
  } else {
    this.buffers = null;
  }
}
ShapePath.prototype = {
  get isEmpty() {
    return this.commands.length === 0;
  },
  moveTo: function (x, y) {
    if (this.commands[this.commands.length - 1] === SHAPE_MOVE_TO) {
      this.data[this.data.length - 2] = x;
      this.data[this.data.length - 1] = y;
      return;
    }
    this.commands.push(SHAPE_MOVE_TO);
    this.data.push(x, y);
  },
  lineTo: function (x, y) {
    this.commands.push(SHAPE_LINE_TO);
    this.data.push(x, y);
  },
  curveTo: function (controlX, controlY, anchorX, anchorY) {
    this.commands.push(SHAPE_CURVE_TO);
    this.data.push(controlX, controlY, anchorX, anchorY);
  },
  cubicCurveTo: function (control1X, control1Y, control2X, control2Y, anchorX, anchorY) {
    this.commands.push(SHAPE_CUBIC_CURVE_TO);
    this.data.push(control1X, control1Y, control2X, control2Y, anchorX, anchorY);
  },
  rect: function (x, y, w, h) {
    var x2 = x + w;
    var y2 = y + h;
    this.commands.push(SHAPE_MOVE_TO, SHAPE_LINE_TO, SHAPE_LINE_TO, SHAPE_LINE_TO, SHAPE_LINE_TO);
    this.data.push(x, y, x2, y, x2, y2, x, y2, x, y);
  },
  circle: function (x, y, radius) {
    this.commands.push(SHAPE_CIRCLE);
    this.data.push(x, y, radius);
  },
  ellipse: function (x, y, radiusX, radiusY) {
    this.commands.push(SHAPE_ELLIPSE);
    this.data.push(x, y, radiusX, radiusY);
  },
  draw: function (ctx, clip, ratio, colorTransform) {
    if (clip && !this.fillStyle) {
      return;
    }
    ctx.beginPath();
    var commands = this.commands;
    var data = this.data;
    var morphData = this.morphData;
    var formOpen = false;
    var formOpenX = 0;
    var formOpenY = 0;
    if (!this.isMorph) {
      for (var j = 0, k = 0; j < commands.length; j++) {
        switch (commands[j]) {
        case SHAPE_MOVE_TO:
          formOpen = true;
          formOpenX = data[k++] / 20;
          formOpenY = data[k++] / 20;
          ctx.moveTo(formOpenX, formOpenY);
          break;
        case SHAPE_WIDE_MOVE_TO:
          ctx.moveTo(data[k++] / 20, data[k++] / 20);
          k += 2;
          break;
        case SHAPE_LINE_TO:
          ctx.lineTo(data[k++] / 20, data[k++] / 20);
          break;
        case SHAPE_WIDE_LINE_TO:
          ctx.lineTo(data[k++] / 20, data[k++] / 20);
          k += 2;
          break;
        case SHAPE_CURVE_TO:
          ctx.quadraticCurveTo(data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20);
          break;
        case SHAPE_CUBIC_CURVE_TO:
          ctx.bezierCurveTo(data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20);
          break;
        case SHAPE_CIRCLE:
          if (formOpen) {
            ctx.lineTo(formOpenX, formOpenY);
            formOpen = false;
          }
          ctx.moveTo((data[k] + data[k + 2]) / 20, data[k + 1] / 20);
          ctx.arc(data[k++] / 20, data[k++] / 20, data[k++] / 20, 0, Math.PI * 2, false);
          break;
        case SHAPE_ELLIPSE:
          if (formOpen) {
            ctx.lineTo(formOpenX, formOpenY);
            formOpen = false;
          }
          var x = data[k++];
          var y = data[k++];
          var rX = data[k++];
          var rY = data[k++];
          var radius;
          if (rX !== rY) {
            ctx.save();
            var ellipseScale;
            if (rX > rY) {
              ellipseScale = rX / rY;
              radius = rY;
              x /= ellipseScale;
              ctx.scale(ellipseScale, 1);
            } else {
              ellipseScale = rY / rX;
              radius = rX;
              y /= ellipseScale;
              ctx.scale(1, ellipseScale);
            }
          }
          ctx.moveTo((x + radius) / 20, y / 20);
          ctx.arc(x / 20, y / 20, radius / 20, 0, Math.PI * 2, false);
          if (rX !== rY) {
            ctx.restore();
          }
          break;
        default:
          if (commands[j] === 0 && j === commands.length - 1) {
            break;
          }
          console.warn('Unknown drawing command encountered: ' + commands[j]);
        }
      }
    } else {
      for (var j = 0, k = 0; j < commands.length; j++) {
        switch (commands[j]) {
        case SHAPE_MOVE_TO:
          ctx.moveTo(morph(data[k] / 20, morphData[k++] / 20, ratio), morph(data[k] / 20, morphData[k++] / 20, ratio));
          break;
        case SHAPE_LINE_TO:
          ctx.lineTo(morph(data[k] / 20, morphData[k++] / 20, ratio), morph(data[k] / 20, morphData[k++] / 20, ratio));
          break;
        case SHAPE_CURVE_TO:
          ctx.quadraticCurveTo(morph(data[k] / 20, morphData[k++] / 20, ratio), morph(data[k] / 20, morphData[k++] / 20, ratio), morph(data[k] / 20, morphData[k++] / 20, ratio), morph(data[k] / 20, morphData[k++] / 20, ratio));
          break;
        default:
          console.warn('Drawing command not supported for morph shapes: ' + commands[j]);
        }
      }
    }
    if (!clip) {
      var fillStyle = this.fillStyle;
      if (fillStyle) {
        colorTransform.setFillStyle(ctx, fillStyle.style);
        ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = fillStyle.smooth;
        var m = fillStyle.transform;
        ctx.save();
        colorTransform.setAlpha(ctx);
        if (m) {
          ctx.transform(m.a, m.b, m.c, m.d, m.e / 20, m.f / 20);
        }
        ctx.fill();
        ctx.restore();
      }
      var lineStyle = this.lineStyle;
      if (lineStyle) {
        colorTransform.setStrokeStyle(ctx, lineStyle.style);
        ctx.save();
        colorTransform.setAlpha(ctx);
        ctx.lineWidth = Math.max(lineStyle.width / 20, 1);
        ctx.lineCap = lineStyle.lineCap;
        ctx.lineJoin = lineStyle.lineJoin;
        ctx.miterLimit = lineStyle.miterLimit;
        ctx.stroke();
        ctx.restore();
      }
    } else {
      ctx.fill();
    }
    ctx.closePath();
  },
  isPointInPath: function (x, y) {
    if (!(this.fillStyle || this.lineStyle)) {
      return false;
    }
    var bounds = this.strokeBounds || this.bounds || this._calculateBounds();
    if (x < bounds.xMin || x > bounds.xMax || y < bounds.yMin || y > bounds.yMax) {
      return false;
    }
    if (this.fillStyle && this.isPointInFill(x, y)) {
      return true;
    }
    return this.lineStyle && this.lineStyle.width !== undefined && this.isPointInStroke(x, y);
  },
  isPointInFill: function (x, y) {
    var commands = this.commands;
    var data = this.data;
    var length = commands.length;
    var inside = false;
    var fromX = 0;
    var fromY = 0;
    var toX = 0;
    var toY = 0;
    var localX;
    var localY;
    var cpX;
    var cpY;
    var rX;
    var rY;
    var formOpen = false;
    var formOpenX = 0;
    var formOpenY = 0;
    for (var commandIndex = 0, dataIndex = 0; commandIndex < length; commandIndex++) {
      switch (commands[commandIndex]) {
      case SHAPE_WIDE_MOVE_TO:
        dataIndex += 2;
      case SHAPE_MOVE_TO:
        toX = data[dataIndex++];
        toY = data[dataIndex++];
        if (formOpen && intersectsLine(x, y, fromX, fromY, formOpenX, formOpenY)) {
          inside = !inside;
        }
        formOpen = true;
        formOpenX = toX;
        formOpenY = toY;
        break;
      case SHAPE_WIDE_LINE_TO:
        dataIndex += 2;
      case SHAPE_LINE_TO:
        toX = data[dataIndex++];
        toY = data[dataIndex++];
        if (intersectsLine(x, y, fromX, fromY, toX, toY)) {
          inside = !inside;
        }
        break;
      case SHAPE_CURVE_TO:
        cpX = data[dataIndex++];
        cpY = data[dataIndex++];
        toX = data[dataIndex++];
        toY = data[dataIndex++];
        if (cpY > y === fromY > y && toY > y === fromY > y) {
          break;
        }
        if (fromX >= x && cpX >= x && toX >= x) {
          inside = !inside;
          break;
        }
        var a = fromY - 2 * cpY + toY;
        var c = fromY - y;
        var b = 2 * (cpY - fromY);
        var d = b * b - 4 * a * c;
        if (d < 0) {
          break;
        }
        d = Math.sqrt(d);
        a = 1 / (a + a);
        var t1 = (d - b) * a;
        var t2 = (-b - d) * a;
        if (t1 >= 0 && t1 <= 1 && quadraticBezier(fromX, cpX, toX, t1) > x) {
          inside = !inside;
        }
        if (t2 >= 0 && t2 <= 1 && quadraticBezier(fromX, cpX, toX, t2) > x) {
          inside = !inside;
        }
        break;
      case SHAPE_CUBIC_CURVE_TO:
        cpX = data[dataIndex++];
        cpY = data[dataIndex++];
        var cp2X = data[dataIndex++];
        var cp2Y = data[dataIndex++];
        toX = data[dataIndex++];
        toY = data[dataIndex++];
        if (cpY > y === fromY > y && cp2Y > y === fromY > y && toY > y === fromY > y) {
          break;
        }
        if (fromX >= x && cpX >= x && cp2X >= x && toX >= x) {
          inside = !inside;
          break;
        }
        var roots = cubicXAtY(fromX, fromY, cpX, cpY, cp2X, cp2Y, toX, toY, y);
        for (var i = roots.length; i--;) {
          if (roots[i] >= x) {
            inside = !inside;
          }
        }
        break;
      case SHAPE_CIRCLE:
        toX = data[dataIndex++];
        toY = data[dataIndex++];
        var r = data[dataIndex++];
        localX = x - toX;
        localY = y - toY;
        if (localX * localX + localY * localY < r * r) {
          inside = !inside;
        }
        toX += r;
        break;
      case SHAPE_ELLIPSE:
        cpX = data[dataIndex++];
        cpY = data[dataIndex++];
        rX = data[dataIndex++];
        rY = data[dataIndex++];
        localX = x - cpX;
        localY = y - cpY;
        if (localX * localX / (rX * rX) + localY * localY / (rY * rY) <= 1) {
          inside = !inside;
        }
        toX = cpX + rX;
        toY = cpY;
        break;
      default:
        if (!inWorker) {
          console.warn('Drawing command not handled in isPointInPath: ' + commands[commandIndex]);
        }
      }
      fromX = toX;
      fromY = toY;
    }
    if (formOpen && intersectsLine(x, y, fromX, fromY, formOpenX, formOpenY)) {
      inside = !inside;
    }
    return inside;
  },
  isPointInStroke: function (x, y) {
    var commands = this.commands;
    var data = this.data;
    var length = commands.length;
    var width = this.lineStyle.width;
    var halfWidth = width / 2;
    var halfWidthSq = halfWidth * halfWidth;
    var minX = x - halfWidth;
    var maxX = x + halfWidth;
    var minY = y - halfWidth;
    var maxY = y + halfWidth;
    var fromX = 0;
    var fromY = 0;
    var toX = 0;
    var toY = 0;
    var localX;
    var localY;
    var cpX;
    var cpY;
    var rX;
    var rY;
    var curveX;
    var curveY;
    var t;
    for (var commandIndex = 0, dataIndex = 0; commandIndex < length; commandIndex++) {
      switch (commands[commandIndex]) {
      case SHAPE_WIDE_MOVE_TO:
        dataIndex += 2;
      case SHAPE_MOVE_TO:
        toX = data[dataIndex++];
        toY = data[dataIndex++];
        break;
      case SHAPE_WIDE_LINE_TO:
        dataIndex += 2;
      case SHAPE_LINE_TO:
        toX = data[dataIndex++];
        toY = data[dataIndex++];
        if (fromX === toX && fromY === toY) {
          break;
        }
        if (maxX < fromX && maxX < toX || minX > fromX && minX > toX || maxY < fromY && maxY < toY || minY > fromY && minY > toY) {
          break;
        }
        if (toX === fromX || toY === fromY) {
          return true;
        }
        t = ((x - fromX) * (toX - fromX) + (y - fromY) * (toY - fromY)) / distanceSq(fromX, fromY, toX, toY);
        if (t < 0) {
          if (distanceSq(x, y, fromX, fromY) <= halfWidthSq) {
            return true;
          }
          break;
        }
        if (t > 1) {
          if (distanceSq(x, y, toX, toY) <= halfWidthSq) {
            return true;
          }
          break;
        }
        if (distanceSq(x, y, fromX + t * (toX - fromX), fromY + t * (toY - fromY)) <= halfWidthSq) {
          return true;
        }
        break;
      case SHAPE_CURVE_TO:
        cpX = data[dataIndex++];
        cpY = data[dataIndex++];
        toX = data[dataIndex++];
        toY = data[dataIndex++];
        var extremeX = quadraticBezierExtreme(fromX, cpX, toX);
        if (maxX < fromX && maxX < extremeX && maxX < toX || minX > fromX && minX > extremeX && minX > toX) {
          break;
        }
        var extremeY = quadraticBezierExtreme(fromY, cpY, toY);
        if (maxY < fromY && maxY < extremeY && maxY < toY || minY > fromY && minY > extremeY && minY > toY) {
          break;
        }
        for (t = 0; t < 1; t += 0.02) {
          curveX = quadraticBezier(fromX, cpX, toX, t);
          if (curveX < minX || curveX > maxX) {
            continue;
          }
          curveY = quadraticBezier(fromY, cpY, toY, t);
          if (curveY < minY || curveY > maxY) {
            continue;
          }
          if ((x - curveX) * (x - curveX) + (y - curveY) * (y - curveY) < halfWidthSq) {
            return true;
          }
        }
        break;
      case SHAPE_CUBIC_CURVE_TO:
        cpX = data[dataIndex++];
        cpY = data[dataIndex++];
        var cp2X = data[dataIndex++];
        var cp2Y = data[dataIndex++];
        toX = data[dataIndex++];
        toY = data[dataIndex++];
        var extremesX = cubicBezierExtremes(fromX, cpX, cp2X, toX);
        while (extremesX.length < 2) {
          extremesX.push(toX);
        }
        if (maxX < fromX && maxX < toX && maxX < extremesX[0] && maxX < extremesX[1] || minX > fromX && minX > toX && minX > extremesX[0] && minX > extremesX[1]) {
          break;
        }
        var extremesY = cubicBezierExtremes(fromY, cpY, cp2Y, toY);
        while (extremesY.length < 2) {
          extremesY.push(toY);
        }
        if (maxY < fromY && maxY < toY && maxY < extremesY[0] && maxY < extremesY[1] || minY > fromY && minY > toY && minY > extremesY[0] && minY > extremesY[1]) {
          break;
        }
        for (t = 0; t < 1; t += 0.02) {
          curveX = cubicBezier(fromX, cpX, cp2X, toX, t);
          if (curveX < minX || curveX > maxX) {
            continue;
          }
          curveY = cubicBezier(fromY, cpY, cp2Y, toY, t);
          if (curveY < minY || curveY > maxY) {
            continue;
          }
          if ((x - curveX) * (x - curveX) + (y - curveY) * (y - curveY) < halfWidthSq) {
            return true;
          }
        }
        break;
      case SHAPE_CIRCLE:
        cpX = data[dataIndex++];
        cpY = data[dataIndex++];
        var r = data[dataIndex++];
        toX = cpX + r;
        toY = cpY;
        if (maxX < cpX - r || minX > cpX + r || maxY < cpY - r || minY > cpY + r) {
          break;
        }
        localX = x - cpX;
        localY = y - cpY;
        var rMin = r - halfWidth;
        var rMax = r + halfWidth;
        var distSq = localX * localX + localY * localY;
        if (distSq >= rMin * rMin && distSq <= rMax * rMax) {
          return true;
        }
        break;
      case SHAPE_ELLIPSE:
        cpX = data[dataIndex++];
        cpY = data[dataIndex++];
        rX = data[dataIndex++];
        rY = data[dataIndex++];
        toX = cpX + rX;
        toY = cpY;
        localX = Math.abs(x - cpX);
        localY = Math.abs(y - cpY);
        localX -= halfWidth;
        localY -= halfWidth;
        if (localX * localX / (rX * rX) + localY * localY / (rY * rY) > 1) {
          break;
        }
        localX += width;
        localY += width;
        if (localX * localX / (rX * rX) + localY * localY / (rY * rY) > 1) {
          return true;
        }
        break;
      default:
        if (!inWorker) {
          console.warn('Drawing command not handled in isPointInPath: ' + commands[commandIndex]);
        }
      }
      fromX = toX;
      fromY = toY;
    }
    return false;
  },
  getBounds: function (includeStroke) {
    var bounds = includeStroke ? this.strokeBounds : this.bounds;
    if (!bounds) {
      this._calculateBounds();
      bounds = includeStroke ? this.strokeBounds : this.bounds;
    }
    return bounds;
  },
  _calculateBounds: function () {
    var commands = this.commands;
    var data = this.data;
    var length = commands.length;
    var bounds;
    if (commands[0] === SHAPE_MOVE_TO || commands[0] > SHAPE_CUBIC_CURVE_TO) {
      bounds = {
        xMin: data[0],
        yMin: data[1]
      };
    } else {
      bounds = {
        xMin: 0,
        yMin: 0
      };
    }
    bounds.xMax = bounds.xMin;
    bounds.yMax = bounds.yMin;
    var fromX = bounds.xMin;
    var fromY = bounds.yMin;
    for (var commandIndex = 0, dataIndex = 0; commandIndex < length; commandIndex++) {
      var toX;
      var toY;
      var cpX;
      var cpY;
      switch (commands[commandIndex]) {
      case SHAPE_WIDE_MOVE_TO:
        dataIndex += 2;
      case SHAPE_MOVE_TO:
        toX = data[dataIndex++];
        toY = data[dataIndex++];
        extendBoundsByPoint(bounds, toX, toY);
        break;
      case SHAPE_WIDE_LINE_TO:
        dataIndex += 2;
      case SHAPE_LINE_TO:
        toX = data[dataIndex++];
        toY = data[dataIndex++];
        extendBoundsByPoint(bounds, toX, toY);
        break;
      case SHAPE_CURVE_TO:
        cpX = data[dataIndex++];
        cpY = data[dataIndex++];
        toX = data[dataIndex++];
        toY = data[dataIndex++];
        extendBoundsByPoint(bounds, toX, toY);
        if (cpX < fromX || cpX > toX) {
          extendBoundsByX(bounds, quadraticBezierExtreme(fromX, cpX, toX));
        }
        if (cpY < fromY || cpY > toY) {
          extendBoundsByY(bounds, quadraticBezierExtreme(fromY, cpY, toY));
        }
        break;
      case SHAPE_CUBIC_CURVE_TO:
        cpX = data[dataIndex++];
        cpY = data[dataIndex++];
        var cp2X = data[dataIndex++];
        var cp2Y = data[dataIndex++];
        toX = data[dataIndex++];
        toY = data[dataIndex++];
        extendBoundsByPoint(bounds, toX, toY);
        var extremes;
        var i;
        if (cpX < fromX || cp2X < fromX || cpX > toX || cp2X > toX) {
          extremes = cubicBezierExtremes(fromX, cpX, cp2X, toX);
          for (i = extremes.length; i--;) {
            extendBoundsByX(bounds, extremes[i]);
          }
        }
        if (cpY < fromY || cp2Y < fromY || cpY > toY || cp2Y > toY) {
          extremes = cubicBezierExtremes(fromY, cpY, cp2Y, toY);
          for (i = extremes.length; i--;) {
            extendBoundsByY(bounds, extremes[i]);
          }
        }
        break;
      case SHAPE_CIRCLE:
        toX = data[dataIndex++];
        toY = data[dataIndex++];
        var radius = data[dataIndex++];
        extendBoundsByPoint(bounds, toX - radius, toY - radius);
        extendBoundsByPoint(bounds, toX + radius, toY + radius);
        toX += radius;
        break;
      case SHAPE_ELLIPSE:
        toX = data[dataIndex++];
        toY = data[dataIndex++];
        var radiusX = data[dataIndex++];
        var radiusY = data[dataIndex++];
        extendBoundsByPoint(bounds, toX - radiusX, toY - radiusY);
        extendBoundsByPoint(bounds, toX + radiusX, toY + radiusY);
        toX += radiusX;
        break;
      default:
        if (!inWorker) {
          console.warn('Drawing command not handled in bounds calculation: ' + commands[commandIndex]);
        }
      }
      fromX = toX;
      fromY = toY;
    }
    this.bounds = bounds;
    if (this.lineStyle) {
      var halfLineWidth = this.lineStyle.width / 2;
      this.strokeBounds = {
        xMin: bounds.xMin - halfLineWidth,
        yMin: bounds.yMin - halfLineWidth,
        xMax: bounds.xMax + halfLineWidth,
        yMax: bounds.yMax + halfLineWidth
      };
      return this.strokeBounds;
    } else {
      this.strokeBounds = bounds;
    }
    return bounds;
  },
  serialize: function () {
    var output = '{';
    if (this.fillStyle) {
      output += '"fill":' + JSON.stringify(this.fillStyle) + ',';
    }
    if (this.lineStyle) {
      output += '"stroke":' + JSON.stringify(this.lineStyle) + ',';
    }
    output += '"commands":[' + Array.apply([], this.commands).join() + '],';
    output += '"data":[' + Array.apply([], this.data).join() + ']';
    return output + '}';
  }
};
ShapePath.fromPlainObject = function (obj) {
  var path = new ShapePath(obj.fill || null, obj.stroke || null);
  path.commands = new Uint8Array(obj.commands);
  path.data = new Int32Array(obj.data);
  if (!inWorker) {
    finishShapePath(path);
  }
  return path;
};
function distanceSq(x1, y1, x2, y2) {
  var dX = x2 - x1;
  var dY = y2 - y1;
  return dX * dX + dY * dY;
}
function intersectsLine(x, y, x1, y1, x2, y2) {
  return y2 > y !== y1 > y && x < (x1 - x2) * (y - y2) / (y1 - y2) + x2;
}
function quadraticBezier(from, cp, to, t) {
  var inverseT = 1 - t;
  return from * inverseT * inverseT + 2 * cp * inverseT * t + to * t * t;
}
function quadraticBezierExtreme(from, cp, to) {
  var t = (from - cp) / (from - 2 * cp + to);
  if (t < 0) {
    return from;
  }
  if (t > 1) {
    return to;
  }
  return quadraticBezier(from, cp, to, t);
}
function cubicBezier(from, cp, cp2, to, t) {
  var tSq = t * t;
  var inverseT = 1 - t;
  var inverseTSq = inverseT * inverseT;
  return from * inverseT * inverseTSq + 3 * cp * t * inverseTSq + 3 * cp2 * inverseT * tSq + to * t * tSq;
}
function cubicBezierExtremes(from, cp, cp2, to) {
  var d1 = cp - from;
  var d2 = cp2 - cp;
  d2 *= 2;
  var d3 = to - cp2;
  if (d1 + d3 === d2) {
    d3 *= 1.0001;
  }
  var fHead = 2 * d1 - d2;
  var part1 = d2 - 2 * d1;
  var fCenter = Math.sqrt(part1 * part1 - 4 * d1 * (d1 - d2 + d3));
  var fTail = 2 * (d1 - d2 + d3);
  var t1 = (fHead + fCenter) / fTail;
  var t2 = (fHead - fCenter) / fTail;
  var result = [];
  if (t1 >= 0 && t1 <= 1) {
    result.push(cubicBezier(from, cp, cp2, to, t1));
  }
  if (t2 >= 0 && t2 <= 1) {
    result.push(cubicBezier(from, cp, cp2, to, t2));
  }
  return result;
}
function cubicXAtY(x0, y0, cx, cy, cx1, cy1, x1, y1, y) {
  var dX = 3 * (cx - x0);
  var dY = 3 * (cy - y0);
  var bX = 3 * (cx1 - cx) - dX;
  var bY = 3 * (cy1 - cy) - dY;
  var c3X = x1 - x0 - dX - bX;
  var c3Y = y1 - y0 - dY - bY;
  function f(t) {
    return t * (dY + t * (bY + t * c3Y)) + y0 - y;
  }
  function pointAt(t) {
    if (t < 0) {
      t = 0;
    } else if (t > 1) {
      t = 1;
    }
    return x0 + t * (dX + t * (bX + t * c3X));
  }
  function bisectCubicBezierRange(f, l, r, limit) {
    if (Math.abs(r - l) <= limit) {
      return;
    }
    var middle = 0.5 * (l + r);
    if (f(l) * f(r) <= 0) {
      left = l;
      right = r;
      return;
    }
    bisectCubicBezierRange(f, l, middle, limit);
    bisectCubicBezierRange(f, middle, r, limit);
  }
  var left = 0;
  var right = 1;
  bisectCubicBezierRange(f, 0, 1, 0.05);
  var t0 = findRoot(left, right, f, 50, 0.000001);
  var evalResult = Math.abs(f(t0));
  if (evalResult > 0.00001) {
    return [];
  }
  var result = [];
  if (t0 <= 1) {
    result.push(pointAt(t0));
  }
  var a = c3Y;
  var b = t0 * a + bY;
  var c = t0 * b + dY;
  var d = b * b - 4 * a * c;
  if (d < 0) {
    return result;
  }
  d = Math.sqrt(d);
  a = 1 / (a + a);
  var t1 = (d - b) * a;
  var t2 = (-b - d) * a;
  if (t1 >= 0 && t1 <= 1) {
    result.push(pointAt(t1));
  }
  if (t2 >= 0 && t2 <= 1) {
    result.push(pointAt(t2));
  }
  return result;
}
function findRoot(x0, x2, f, maxIterations, epsilon) {
  var x1;
  var y0;
  var y1;
  var y2;
  var b;
  var c;
  var y10;
  var y20;
  var y21;
  var xm;
  var ym;
  var temp;
  var xmlast = x0;
  y0 = f(x0);
  if (y0 === 0) {
    return x0;
  }
  y2 = f(x2);
  if (y2 === 0) {
    return x2;
  }
  if (y2 * y0 > 0) {
    return x0;
  }
  var __iter = 0;
  for (var i = 0; i < maxIterations; ++i) {
    __iter++;
    x1 = 0.5 * (x2 + x0);
    y1 = f(x1);
    if (y1 === 0) {
      return x1;
    }
    if (Math.abs(x1 - x0) < epsilon) {
      return x1;
    }
    if (y1 * y0 > 0) {
      temp = x0;
      x0 = x2;
      x2 = temp;
      temp = y0;
      y0 = y2;
      y2 = temp;
    }
    y10 = y1 - y0;
    y21 = y2 - y1;
    y20 = y2 - y0;
    if (y2 * y20 < 2 * y1 * y10) {
      x2 = x1;
      y2 = y1;
    } else {
      b = (x1 - x0) / y10;
      c = (y10 - y21) / (y21 * y20);
      xm = x0 - b * y0 * (1 - c * y1);
      ym = f(xm);
      if (ym === 0) {
        return xm;
      }
      if (Math.abs(xm - xmlast) < epsilon) {
        return xm;
      }
      xmlast = xm;
      if (ym * y0 < 0) {
        x2 = xm;
        y2 = ym;
      } else {
        x0 = xm;
        y0 = ym;
        x2 = x1;
        y2 = y1;
      }
    }
  }
  return x1;
}
function extendBoundsByPoint(bounds, x, y) {
  if (x < bounds.xMin) {
    bounds.xMin = x;
  } else if (x > bounds.xMax) {
    bounds.xMax = x;
  }
  if (y < bounds.yMin) {
    bounds.yMin = y;
  } else if (y > bounds.yMax) {
    bounds.yMax = y;
  }
}
function extendBoundsByX(bounds, x) {
  if (x < bounds.xMin) {
    bounds.xMin = x;
  } else if (x > bounds.xMax) {
    bounds.xMax = x;
  }
}
function extendBoundsByY(bounds, y) {
  if (y < bounds.yMin) {
    bounds.yMin = y;
  } else if (y > bounds.yMax) {
    bounds.yMax = y;
  }
}
function morph(start, end, ratio) {
  return start + (end - start) * ratio;
}
function finishShapePath(path, dictionaryResolved) {
  if (path.fullyInitialized) {
    return path;
  }
  if (!(path instanceof ShapePath)) {
    var untypedPath = path;
    path = new ShapePath(path.fillStyle, path.lineStyle, 0, 0, path.isMorph);
    path.commands = new Uint8Array(untypedPath.buffers[0]);
    path.data = new Int32Array(untypedPath.buffers[1]);
    if (untypedPath.isMorph) {
      path.morphData = new Int32Array(untypedPath.buffers[2]);
    }
    path.buffers = null;
  }
  path.fillStyle && initStyle(path.fillStyle, dictionaryResolved);
  path.lineStyle && initStyle(path.lineStyle, dictionaryResolved);
  path.fullyInitialized = true;
  return path;
}
var inWorker = typeof window === 'undefined';
var factoryCtx = !inWorker ? document.createElement('canvas').getContext('2d') : null;
function buildLinearGradientFactory(colorStops) {
  var defaultGradient = factoryCtx.createLinearGradient(-1, 0, 1, 0);
  for (var i = 0; i < colorStops.length; i++) {
    defaultGradient.addColorStop(colorStops[i].ratio, colorStops[i].color);
  }
  var fn = function createLinearGradient(ctx, colorTransform) {
    var gradient = ctx.createLinearGradient(-1, 0, 1, 0);
    for (var i = 0; i < colorStops.length; i++) {
      colorTransform.addGradientColorStop(gradient, colorStops[i].ratio, colorStops[i].color);
    }
    return gradient;
  };
  fn.defaultFillStyle = defaultGradient;
  return fn;
}
function buildRadialGradientFactory(focalPoint, colorStops) {
  var defaultGradient = factoryCtx.createRadialGradient(focalPoint, 0, 0, 0, 0, 1);
  for (var i = 0; i < colorStops.length; i++) {
    defaultGradient.addColorStop(colorStops[i].ratio, colorStops[i].color);
  }
  var fn = function createRadialGradient(ctx, colorTransform) {
    var gradient = ctx.createRadialGradient(focalPoint, 0, 0, 0, 0, 1);
    for (var i = 0; i < colorStops.length; i++) {
      colorTransform.addGradientColorStop(gradient, colorStops[i].ratio, colorStops[i].color);
    }
    return gradient;
  };
  fn.defaultFillStyle = defaultGradient;
  return fn;
}
function buildBitmapPatternFactory(img, repeat) {
  var defaultPattern = factoryCtx.createPattern(img, repeat);
  var cachedTransform, cachedTransformKey;
  var fn = function createBitmapPattern(ctx, colorTransform) {
    if (!colorTransform.mode) {
      return defaultPattern;
    }
    var key = colorTransform.getTransformFingerprint();
    if (key === cachedTransformKey) {
      return cachedTransform;
    }
    var canvas = document.createElement('canvas');
    canvas.width = img.width;
    canvas.height = img.height;
    var ctx = canvas.getContext('2d');
    colorTransform.setAlpha(ctx, true);
    ctx.drawImage(img, 0, 0);
    cachedTransform = ctx.createPattern(canvas, repeat);
    cachedTransformKey = key;
    return cachedTransform;
  };
  fn.defaultFillStyle = defaultPattern;
  return fn;
}
function initStyle(style, dictionaryResolved) {
  if (style.type === undefined) {
    return;
  }
  switch (style.type) {
  case GRAPHICS_FILL_SOLID:
    break;
  case GRAPHICS_FILL_LINEAR_GRADIENT:
  case GRAPHICS_FILL_RADIAL_GRADIENT:
  case GRAPHICS_FILL_FOCAL_RADIAL_GRADIENT:
    var records = style.records, colorStops = [];
    for (var j = 0, n = records.length; j < n; j++) {
      var record = records[j];
      var colorStr = rgbaObjToStr(record.color);
      colorStops.push({
        ratio: record.ratio / 255,
        color: colorStr
      });
    }
    var gradientConstructor;
    var isLinear = style.type === GRAPHICS_FILL_LINEAR_GRADIENT;
    if (isLinear) {
      gradientConstructor = buildLinearGradientFactory(colorStops);
    } else {
      gradientConstructor = buildRadialGradientFactory((style.focalPoint | 0) / 20, colorStops);
    }
    style.style = gradientConstructor;
    break;
  case GRAPHICS_FILL_REPEATING_BITMAP:
  case GRAPHICS_FILL_CLIPPED_BITMAP:
  case GRAPHICS_FILL_NONSMOOTHED_REPEATING_BITMAP:
  case GRAPHICS_FILL_NONSMOOTHED_CLIPPED_BITMAP:
    var bitmap = dictionaryResolved[style.bitmapId];
    var repeat = style.type === GRAPHICS_FILL_REPEATING_BITMAP || style.type === GRAPHICS_FILL_NONSMOOTHED_REPEATING_BITMAP;
    style.style = buildBitmapPatternFactory(bitmap.props.img, repeat ? 'repeat' : 'no-repeat');
    break;
  default:
    fail('invalid fill style', 'shape');
  }
}
var SOUND_SIZE_8_BIT = 0;
var SOUND_SIZE_16_BIT = 1;
var SOUND_TYPE_MONO = 0;
var SOUND_TYPE_STEREO = 1;
var SOUND_FORMAT_PCM_BE = 0;
var SOUND_FORMAT_ADPCM = 1;
var SOUND_FORMAT_MP3 = 2;
var SOUND_FORMAT_PCM_LE = 3;
var SOUND_FORMAT_NELLYMOSER_16 = 4;
var SOUND_FORMAT_NELLYMOSER_8 = 5;
var SOUND_FORMAT_NELLYMOSER = 6;
var SOUND_FORMAT_SPEEX = 11;
var SOUND_RATES = [
    5512,
    11250,
    22500,
    44100
  ];
var WaveHeader = new Uint8Array([
    82,
    73,
    70,
    70,
    0,
    0,
    0,
    0,
    87,
    65,
    86,
    69,
    102,
    109,
    116,
    32,
    16,
    0,
    0,
    0,
    1,
    0,
    2,
    0,
    68,
    172,
    0,
    0,
    16,
    177,
    2,
    0,
    4,
    0,
    16,
    0,
    100,
    97,
    116,
    97,
    0,
    0,
    0,
    0
  ]);
function packageWave(data, sampleRate, channels, size, swapBytes) {
  var sizeInBytes = size >> 3;
  var sizePerSecond = channels * sampleRate * sizeInBytes;
  var sizePerSample = channels * sizeInBytes;
  var dataLength = data.length + (data.length & 1);
  var buffer = new ArrayBuffer(WaveHeader.length + dataLength);
  var bytes = new Uint8Array(buffer);
  bytes.set(WaveHeader);
  if (swapBytes) {
    for (var i = 0, j = WaveHeader.length; i < data.length; i += 2, j += 2) {
      bytes[j] = data[i + 1];
      bytes[j + 1] = data[i];
    }
  } else {
    bytes.set(data, WaveHeader.length);
  }
  var view = new DataView(buffer);
  view.setUint32(4, dataLength + 36, true);
  view.setUint16(22, channels, true);
  view.setUint32(24, sampleRate, true);
  view.setUint32(28, sizePerSecond, true);
  view.setUint16(32, sizePerSample, true);
  view.setUint16(34, size, true);
  view.setUint32(40, dataLength, true);
  return {
    data: bytes,
    mimeType: 'audio/wav'
  };
}
function defineSound(tag, dictionary) {
  var channels = tag.soundType == SOUND_TYPE_STEREO ? 2 : 1;
  var samplesCount = tag.samplesCount;
  var sampleRate = SOUND_RATES[tag.soundRate];
  var data = tag.soundData;
  var pcm, packaged;
  switch (tag.soundFormat) {
  case SOUND_FORMAT_PCM_BE:
    pcm = new Float32Array(samplesCount * channels);
    if (tag.soundSize == SOUND_SIZE_16_BIT) {
      for (var i = 0, j = 0; i < pcm.length; i++, j += 2)
        pcm[i] = (data[j] << 24 | data[j + 1] << 16) / 2147483648;
      packaged = packageWave(data, sampleRate, channels, 16, true);
    } else {
      for (var i = 0; i < pcm.length; i++)
        pcm[i] = (data[i] - 128) / 128;
      packaged = packageWave(data, sampleRate, channels, 8, false);
    }
    break;
  case SOUND_FORMAT_PCM_LE:
    pcm = new Float32Array(samplesCount * channels);
    if (tag.soundSize == SOUND_SIZE_16_BIT) {
      for (var i = 0, j = 0; i < pcm.length; i++, j += 2)
        pcm[i] = (data[j + 1] << 24 | data[j] << 16) / 2147483648;
      packaged = packageWave(data, sampleRate, channels, 16, false);
    } else {
      for (var i = 0; i < pcm.length; i++)
        pcm[i] = (data[i] - 128) / 128;
      packaged = packageWave(data, sampleRate, channels, 8, false);
    }
    break;
  case SOUND_FORMAT_MP3:
    packaged = {
      data: new Uint8Array(data.subarray(2)),
      mimeType: 'audio/mpeg'
    };
    break;
  case SOUND_FORMAT_ADPCM:
    var pcm16 = new Int16Array(samplesCount * channels);
    decodeACPCMSoundData(data, pcm16, channels);
    pcm = new Float32Array(samplesCount * channels);
    for (var i = 0; i < pcm.length; i++)
      pcm[i] = pcm16[i] / 32768;
    packaged = packageWave(new Uint8Array(pcm16.buffer), sampleRate, channels, 16, !new Uint8Array(new Uint16Array([
      1
    ]).buffer)[0]);
    break;
  default:
    throw new Error('Unsupported audio format: ' + tag.soundFormat);
  }
  var sound = {
      type: 'sound',
      id: tag.id,
      sampleRate: sampleRate,
      channels: channels,
      pcm: pcm
    };
  if (packaged)
    sound.packaged = packaged;
  return sound;
}
var ACPCMIndexTables = [
    [
      -1,
      2
    ],
    [
      -1,
      -1,
      2,
      4
    ],
    [
      -1,
      -1,
      -1,
      -1,
      2,
      4,
      6,
      8
    ],
    [
      -1,
      -1,
      -1,
      -1,
      -1,
      -1,
      -1,
      -1,
      1,
      2,
      4,
      6,
      8,
      10,
      13,
      16
    ]
  ];
var ACPCMStepSizeTable = [
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    16,
    17,
    19,
    21,
    23,
    25,
    28,
    31,
    34,
    37,
    41,
    45,
    50,
    55,
    60,
    66,
    73,
    80,
    88,
    97,
    107,
    118,
    130,
    143,
    157,
    173,
    190,
    209,
    230,
    253,
    279,
    307,
    337,
    371,
    408,
    449,
    494,
    544,
    598,
    658,
    724,
    796,
    876,
    963,
    1060,
    1166,
    1282,
    1411,
    1552,
    1707,
    1878,
    2066,
    2272,
    2499,
    2749,
    3024,
    3327,
    3660,
    4026,
    4428,
    4871,
    5358,
    5894,
    6484,
    7132,
    7845,
    8630,
    9493,
    10442,
    11487,
    12635,
    13899,
    15289,
    16818,
    18500,
    20350,
    22385,
    24623,
    27086,
    29794,
    32767
  ];
function decodeACPCMSoundData(data, pcm16, channels) {
  function readBits(n, signed) {
    while (dataBufferLength < n) {
      dataBuffer = dataBuffer << 8 | data[dataPosition++];
      dataBufferLength += 8;
    }
    dataBufferLength -= n;
    return dataBuffer >>> dataBufferLength & (1 << n) - 1;
  }
  var dataPosition = 0;
  var dataBuffer = 0;
  var dataBufferLength = 0;
  var pcmPosition = 0;
  var codeSize = readBits(2);
  var indexTable = ACPCMIndexTables[codeSize];
  while (pcmPosition < pcm16.length) {
    var x = pcm16[pcmPosition++] = readBits(16) << 16 >> 16, x2;
    var stepIndex = readBits(6), stepIndex2;
    if (channels > 1) {
      x2 = pcm16[pcmPosition++] = readBits(16) << 16 >> 16;
      stepIndex2 = readBits(6);
    }
    var signMask = 1 << codeSize + 1;
    for (var i = 0; i < 4095; i++) {
      var nibble = readBits(codeSize + 2);
      var step = ACPCMStepSizeTable[stepIndex];
      var sum = 0;
      for (var currentBit = signMask >> 1; currentBit; currentBit >>= 1, step >>= 1) {
        if (nibble & currentBit)
          sum += step;
      }
      x += (nibble & signMask ? -1 : 1) * (sum + step);
      pcm16[pcmPosition++] = x = x < -32768 ? -32768 : x > 32767 ? 32767 : x;
      stepIndex += indexTable[nibble & ~signMask];
      stepIndex = stepIndex < 0 ? 0 : stepIndex > 88 ? 88 : stepIndex;
      if (channels > 1) {
        nibble = readBits(codeSize + 2);
        step = ACPCMStepSizeTable[stepIndex2];
        sum = 0;
        for (var currentBit = signMask >> 1; currentBit; currentBit >>= 1, step >>= 1) {
          if (nibble & currentBit)
            sum += step;
        }
        x2 += (nibble & signMask ? -1 : 1) * (sum + step);
        pcm16[pcmPosition++] = x2 = x2 < -32768 ? -32768 : x2 > 32767 ? 32767 : x2;
        stepIndex2 += indexTable[nibble & ~signMask];
        stepIndex2 = stepIndex2 < 0 ? 0 : stepIndex2 > 88 ? 88 : stepIndex2;
      }
    }
  }
}
var nextSoundStreamId = 0;
function SwfSoundStream(samplesCount, sampleRate, channels) {
  this.streamId = nextSoundStreamId++;
  this.samplesCount = samplesCount;
  this.sampleRate = sampleRate;
  this.channels = channels;
  this.format = null;
  this.currentSample = 0;
}
SwfSoundStream.prototype = {
  get info() {
    return {
      samplesCount: this.samplesCount,
      sampleRate: this.sampleRate,
      channels: this.channels,
      format: this.format,
      streamId: this.streamId
    };
  },
  decode: function (data) {
    throw new Error('SwfSoundStream.decode: not implemented');
  }
};
function SwfSoundStream_decode_PCM(data) {
  var pcm = new Float32Array(data.length);
  for (var i = 0; i < pcm.length; i++)
    pcm[i] = (data[i] - 128) / 128;
  this.currentSample += pcm.length / this.channels;
  return {
    streamId: this.streamId,
    samplesCount: pcm.length / this.channels,
    pcm: pcm
  };
}
function SwfSoundStream_decode_PCM_be(data) {
  var pcm = new Float32Array(data.length / 2);
  for (var i = 0, j = 0; i < pcm.length; i++, j += 2)
    pcm[i] = (data[j] << 24 | data[j + 1] << 16) / 2147483648;
  this.currentSample += pcm.length / this.channels;
  return {
    streamId: this.streamId,
    samplesCount: pcm.length / this.channels,
    pcm: pcm
  };
}
function SwfSoundStream_decode_PCM_le(data) {
  var pcm = new Float32Array(data.length / 2);
  for (var i = 0, j = 0; i < pcm.length; i++, j += 2)
    pcm[i] = (data[j + 1] << 24 | data[j] << 16) / 2147483648;
  this.currentSample += pcm.length / this.channels;
  return {
    streamId: this.streamId,
    samplesCount: pcm.length / this.channels,
    pcm: pcm
  };
}
function SwfSoundStream_decode_MP3(data) {
  var samplesCount = data[1] << 8 | data[0];
  var seek = data[3] << 8 | data[2];
  this.currentSample += samplesCount;
  return {
    streamId: this.streamId,
    samplesCount: samplesCount,
    data: new Uint8Array(data.subarray(4)),
    seek: seek
  };
}
function createSoundStream(tag) {
  var channels = tag.streamType == SOUND_TYPE_STEREO ? 2 : 1;
  var samplesCount = tag.samplesCount;
  var sampleRate = SOUND_RATES[tag.streamRate];
  var stream = new SwfSoundStream(samplesCount, sampleRate, channels);
  switch (tag.streamCompression) {
  case SOUND_FORMAT_PCM_BE:
    stream.format = 'wave';
    if (tag.soundSize == SOUND_SIZE_16_BIT) {
      stream.decode = SwfSoundStream_decode_PCM_be;
    } else {
      stream.decode = SwfSoundStream_decode_PCM;
    }
    break;
  case SOUND_FORMAT_PCM_LE:
    stream.format = 'wave';
    if (tag.soundSize == SOUND_SIZE_16_BIT) {
      stream.decode = SwfSoundStream_decode_PCM_le;
    } else {
      stream.decode = SwfSoundStream_decode_PCM;
    }
    break;
  case SOUND_FORMAT_MP3:
    stream.format = 'mp3';
    stream.decode = SwfSoundStream_decode_MP3;
    break;
  default:
    throw new Error('Unsupported audio format: ' + tag.soundFormat);
  }
  return stream;
}
function defineText(tag, dictionary) {
  var dependencies = [];
  if (tag.hasFont) {
    var font = dictionary[tag.fontId];
    tag.font = font.uniqueName;
    dependencies.push(font.id);
  }
  var props = {
      type: 'text',
      id: tag.id,
      variableName: tag.variableName,
      tag: tag
    };
  if (dependencies.length)
    props.require = dependencies;
  return props;
}
var isWorker = typeof window === 'undefined';
if (isWorker) {
  importScripts('../../../lib/mp3/mp3.js');
  self.addEventListener('message', function (e) {
    var data = e.data;
    var sessionId = data.sessionId;
    try {
      switch (data.action) {
      case 'create':
        var session = new Session(sessionId);
        sessions[sessionId] = session;
        break;
      case 'close':
        var session = sessions[sessionId];
        if (session) {
          session.close();
          sessions[sessionId] = null;
        }
        break;
      case 'decode':
        var session = sessions[sessionId];
        if (!session) {
          throw new Error('mp3 decoding session is unavailable');
        }
        session.decode(data.data);
        break;
      }
    } catch (ex) {
      self.postMessage({
        sessionId: sessionId,
        action: 'error',
        message: ex.message
      });
    }
  }, false);
  var sessions = {};
  function Session(id) {
    this.id = id;
    if (typeof MP3Decoder === 'undefined') {
      throw new Error('mp3 decoder is not available');
    }
    var decoder = new MP3Decoder();
    decoder.onframedata = function (frameData, channels, sampleRate, bitRate) {
      self.postMessage({
        sessionId: this.id,
        action: 'frame',
        frameData: frameData,
        channels: channels,
        sampleRate: sampleRate,
        bitRate: bitRate
      });
    }.bind(this);
    decoder.onid3tag = function (data) {
      self.postMessage({
        sessionId: this.id,
        action: 'id3',
        id3Data: data
      });
    }.bind(this);
    this.decoder = decoder;
  }
  Session.prototype = {
    decode: function (data) {
      this.decoder.push(data);
    },
    close: function () {
      self.postMessage({
        sessionId: this.id,
        action: 'closed'
      });
    }
  };
  self.console = {
    log: function (s) {
      self.postMessage({
        action: 'console',
        method: 'log',
        message: s
      });
    },
    error: function (s) {
      self.postMessage({
        action: 'console',
        method: 'error',
        message: s
      });
    }
  };
} else {
  var mp3Worker;
  function createMP3Worker() {
    var worker = new Worker(SHUMWAY_ROOT + 'swf/mp3worker.js');
    worker.addEventListener('message', function (e) {
      if (e.data.action === 'console') {
        console[e.data.method].call(console, e.data.message);
      }
    });
    return worker;
  }
  var nextSessionId = 0;
  function MP3DecoderSession() {
    mp3Worker = mp3Worker || createMP3Worker();
    var sessionId = nextSessionId++;
    this.id = sessionId;
    this.onworkermessage = function (e) {
      if (e.data.sessionId !== sessionId)
        return;
      var action = e.data.action;
      switch (action) {
      case 'closed':
        if (this.onclosed)
          this.onclosed();
        mp3Worker.removeEventListener('message', this.onworkermessage, false);
        break;
      case 'frame':
        this.onframedata(e.data.frameData, e.data.channels, e.data.sampleRate, e.data.bitRate);
        break;
      case 'id3':
        if (this.onid3tag)
          this.onid3tag(e.data.id3Data);
        break;
      case 'error':
        if (this.onerror)
          this.onerror(e.data.message);
        break;
      }
    }.bind(this);
    mp3Worker.addEventListener('message', this.onworkermessage, false);
    mp3Worker.postMessage({
      sessionId: sessionId,
      action: 'create'
    });
  }
  MP3DecoderSession.prototype = {
    pushAsync: function (data) {
      mp3Worker.postMessage({
        sessionId: this.id,
        action: 'decode',
        data: data
      });
    },
    close: function () {
      mp3Worker.postMessage({
        sessionId: this.id,
        action: 'close'
      });
    }
  };
  MP3DecoderSession.processAll = function (data, onloaded) {
    var currentBufferSize = 8000;
    var currentBuffer = new Float32Array(currentBufferSize);
    var bufferPosition = 0;
    var id3Tags = [];
    var sessionAborted = false;
    var session = new MP3DecoderSession();
    session.onframedata = function (frameData, channels, sampleRate, bitRate) {
      var needed = frameData.length + bufferPosition;
      if (needed > currentBufferSize) {
        do {
          currentBufferSize *= 2;
        } while (needed > currentBufferSize);
        var newBuffer = new Float32Array(currentBufferSize);
        newBuffer.set(currentBuffer);
        currentBuffer = newBuffer;
      }
      currentBuffer.set(frameData, bufferPosition);
      bufferPosition += frameData.length;
    };
    session.onid3tag = function (tagData) {
      id3Tags.push(tagData);
    };
    session.onclosed = function () {
      if (sessionAborted)
        return;
      onloaded(currentBuffer.subarray(0, bufferPosition), id3Tags);
    };
    session.onerror = function (error) {
      if (sessionAborted)
        return;
      sessionAborted = true;
      onloaded(null, null, error);
    };
    session.pushAsync(data);
    session.close();
  };
}
SWF.embed = function (file, doc, container, options) {
  var canvas = doc.createElement('canvas');
  var ctx = canvas.getContext('2d');
  var loader = new flash.display.Loader();
  var loaderInfo = loader._contentLoaderInfo;
  var stage = new flash.display.Stage();
  var pixelRatio = 1;
  var forceHidpiSetting = forceHidpi.value;
  stage._loader = loader;
  loaderInfo._parameters = options.movieParams;
  loaderInfo._url = options.url || (typeof file === 'string' ? file : null);
  loaderInfo._loaderURL = options.loaderURL || loaderInfo._url;
  loader._parent = stage;
  loader._stage = stage;
  function setCanvasSize(width, height) {
    if (pixelRatio === 1) {
      canvas.width = width | 0;
      canvas.height = height | 0;
      return;
    }
    var canvasWidth = Math.floor(width * pixelRatio);
    var canvasHeight = Math.floor(height * pixelRatio);
    canvas.style.width = canvasWidth / pixelRatio + 'px';
    canvas.style.height = canvasHeight / pixelRatio + 'px';
    canvas.width = canvasWidth;
    canvas.height = canvasHeight;
  }
  function fitCanvas(container) {
    setCanvasSize(container.clientWidth, container.clientHeight);
    stage._invalid = true;
  }
  loaderInfo._addEventListener('init', function () {
    if (forceHidpiSetting || loaderInfo._swfVersion >= 18) {
      pixelRatio = 'devicePixelRatio' in window ? window.devicePixelRatio : 1;
    }
    canvas._pixelRatio = pixelRatio;
    stage._contentsScaleFactor = pixelRatio;
    if (container.clientHeight) {
      fitCanvas(container);
      window.addEventListener('resize', function () {
        fitCanvas(container);
      });
    } else {
      setCanvasSize(stage._stageWidth / 20, stage._stageHeight / 20);
    }
    container.setAttribute('style', 'position: relative');
    canvas.addEventListener('click', function () {
      ShumwayKeyboardListener.focus = stage;
      stage._mouseTarget._dispatchEvent('click');
    });
    canvas.addEventListener('dblclick', function () {
      if (stage._mouseTarget._doubleClickEnabled) {
        stage._mouseTarget._dispatchEvent('doubleClick');
      }
    });
    canvas.addEventListener('mousedown', function () {
      stage._mouseEvents.push('mousedown');
    });
    canvas.addEventListener('mousemove', function (domEvt) {
      var node = this;
      var left = 0;
      var top = 0;
      if (node.offsetParent) {
        do {
          left += node.offsetLeft;
          top += node.offsetTop;
        } while (node = node.offsetParent);
      }
      var m = stage._concatenatedTransform;
      var mouseX = ((domEvt.pageX - left) * pixelRatio - m.tx / 20) / m.a;
      var mouseY = ((domEvt.pageY - top) * pixelRatio - m.ty / 20) / m.d;
      if (mouseX !== stage._mouseX || mouseY !== stage._mouseY) {
        stage._mouseMoved = true;
        stage._mouseX = mouseX * 20;
        stage._mouseY = mouseY * 20;
      }
    });
    canvas.addEventListener('mouseup', function () {
      stage._mouseEvents.push('mouseup');
    });
    canvas.addEventListener('mouseover', function () {
      stage._mouseMoved = true;
      stage._mouseOver = true;
    });
    canvas.addEventListener('mouseout', function () {
      stage._mouseMoved = true;
      stage._mouseOver = false;
    });
    window.addEventListener('message', function (evt) {
      var data = evt.data;
      if (typeof data !== 'object' || data === null) {
        return;
      }
      var type = data.type;
      switch (type) {
      case 'mousemove':
      case 'mouseup':
      case 'mousedown':
        var isMouseMove = type === 'mousemove';
        stage._mouseMoved = true;
        stage._mouseOver = true;
        stage._mouseX = data.x * 20;
        stage._mouseY = data.y * 20;
        if (!isMouseMove) {
          stage._mouseEvents.push(type);
        }
        break;
      case 'mouseover':
      case 'mouseout':
        stage._mouseMoved = true;
        stage._mouseOver = type === 'mouseover';
        break;
      case 'keyup':
      case 'keydown':
        stage._dispatchEvent(new flash.events.KeyboardEvent(type === 'keyup' ? 'keyUp' : 'keyDown', true, false, data.charCode, data.keyCode, data.keyLocation, data.ctrlKey || false, data.altKey || false, data.shiftKey || false));
        break;
      }
    }, false);
    var bgcolor = loaderInfo._backgroundColor;
    if (options.objectParams) {
      var m;
      if (options.objectParams.bgcolor && (m = /#([0-9A-F]{6})/i.exec(options.objectParams.bgcolor))) {
        var hexColor = parseInt(m[1], 16);
        bgcolor = {
          red: hexColor >> 16 & 255,
          green: hexColor >> 8 & 255,
          blue: hexColor & 255,
          alpha: 255
        };
      }
      if (options.objectParams.wmode === 'transparent') {
        bgcolor = {
          red: 0,
          green: 0,
          blue: 0,
          alpha: 0
        };
      }
    }
    stage._color = bgcolor;
    ctx.fillStyle = rgbaObjToStr(bgcolor);
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    var root = loader._content;
    root._dispatchEvent('added', undefined, true);
    root._dispatchEvent('addedToStage');
    container.appendChild(canvas);
    stage._domContainer = container;
    if (options.onStageInitialized) {
      options.onStageInitialized(stage);
    }
    var startPromise = options.startPromise || Promise.resolve();
    startPromise.then(function () {
      renderStage(stage, ctx, options);
    });
  });
  if (options.onParsed) {
    loaderInfo._addEventListener('parsed', function () {
      options.onParsed();
    });
  }
  if (options.onComplete) {
    loaderInfo._addEventListener('complete', function () {
      options.onComplete();
    });
  }
  loader._load(typeof file === 'string' ? new flash.net.URLRequest(file) : file);
  return loader;
};
var rendererOptions = coreOptions.register(new OptionSet('Renderer Options'));
var traceRenderer = rendererOptions.register(new Option('tr', 'traceRenderer', 'number', 0, 'trace renderer execution'));
var disableRenderVisitor = rendererOptions.register(new Option('drv', 'disableRenderVisitor', 'boolean', false, 'disable render visitor'));
var disableMouseVisitor = rendererOptions.register(new Option('dmv', 'disableMouseVisitor', 'boolean', false, 'disable mouse visitor'));
var showRedrawRegions = rendererOptions.register(new Option('rr', 'showRedrawRegions', 'boolean', false, 'show redraw regions'));
var renderAsWireframe = rendererOptions.register(new Option('raw', 'renderAsWireframe', 'boolean', false, 'render as wireframe'));
var showQuadTree = rendererOptions.register(new Option('qt', 'showQuadTree', 'boolean', false, 'show quad tree'));
var turboMode = rendererOptions.register(new Option('', 'turbo', 'boolean', false, 'turbo mode'));
var forceHidpi = rendererOptions.register(new Option('', 'forceHidpi', 'boolean', false, 'force hidpi'));
var skipFrameDraw = rendererOptions.register(new Option('', 'skipFrameDraw', 'boolean', false, 'skip frame when not on time'));
var hud = rendererOptions.register(new Option('', 'hud', 'boolean', false, 'show hud mode'));
var dummyAnimation = rendererOptions.register(new Option('', 'dummy', 'boolean', false, 'show test balls animation'));
var enableConstructChildren = rendererOptions.register(new Option('', 'constructChildren', 'boolean', true, 'Construct Children'));
var enableEnterFrame = rendererOptions.register(new Option('', 'enterFrame', 'boolean', true, 'Enter Frame'));
var enableAdvanceFrame = rendererOptions.register(new Option('', 'advanceFrame', 'boolean', true, 'Advance Frame'));
var CanvasCache = {
    cache: [],
    getCanvas: function getCanvas(protoCanvas) {
      var tempCanvas = this.cache.shift();
      if (!tempCanvas) {
        tempCanvas = {
          canvas: document.createElement('canvas')
        };
        tempCanvas.ctx = tempCanvas.canvas.getContext('2d');
      }
      tempCanvas.canvas.width = protoCanvas.width;
      tempCanvas.canvas.height = protoCanvas.height;
      tempCanvas.ctx.save();
      return tempCanvas;
    },
    releaseCanvas: function releaseCanvas(tempCanvas) {
      tempCanvas.ctx.restore();
      this.cache.push(tempCanvas);
    }
  };
function isCanvasVisible(canvas) {
  if (canvas.ownerDocument.hidden) {
    return false;
  }
  if (canvas.mozVisible === false) {
    return false;
  }
  return true;
}
function visitContainer(container, visitor, context) {
  var children = container._children;
  visitor.childrenStart(container);
  for (var i = 0, n = children.length; i < n; i++) {
    var child = children[i];
    if (!child) {
      continue;
    }
    if (visitor.ignoreVisibleAttribute || child._visible && !child._maskedObject) {
      visitor.visit(child, visitContainer, context);
    }
  }
  visitor.childrenEnd(container);
}
var BlendModeNameMap = {
    'normal': 'normal',
    'multiply': 'multiply',
    'screen': 'screen',
    'lighten': 'lighten',
    'darken': 'darken',
    'difference': 'difference',
    'overlay': 'overlay',
    'hardlight': 'hard-light'
  };
function getBlendModeName(blendMode) {
  return BlendModeNameMap[blendMode] || 'normal';
}
function RenderVisitor(root, ctx, invalidPath, refreshStage) {
  this.root = root;
  this.ctx = ctx;
  this.depth = 0;
  this.invalidPath = invalidPath;
  this.refreshStage = refreshStage;
  this.clipDepth = null;
  this.clipStack = null;
}
RenderVisitor.prototype = {
  ignoreVisibleAttribute: false,
  start: function () {
    visitContainer(this.root, this, new RenderingContext(this.refreshStage, this.invalidPath));
  },
  startFragment: function (matrix) {
    var root = this.root;
    var currentTransform = root._currentTransform;
    var t = currentTransform;
    if (matrix) {
      t = root._currentTransform = {
        a: matrix.a,
        b: matrix.b,
        c: matrix.c,
        d: matrix.d,
        tx: matrix.tx * 20 | 0,
        ty: matrix.ty * 20 | 0
      };
      root._invalidateTransform();
    }
    var inverse;
    if (t) {
      inverse = new flash.geom.Matrix(t.a, t.b, t.c, t.d, t.tx / 20, t.ty / 20);
      inverse.invert();
      this.ctx.save();
      this.ctx.transform(inverse.a, inverse.b, inverse.c, inverse.d, inverse.tx, inverse.ty);
    }
    this.visit(root, visitContainer, new RenderingContext(this.refreshStage, this.invalidPath));
    if (t) {
      this.ctx.restore();
    }
    if (matrix) {
      root._currentTransform = currentTransform;
      root._invalidateTransform();
    }
  },
  childrenStart: function (parent) {
    if (this.depth === 0) {
      var ctx = this.ctx;
      ctx.save();
      if (this.invalidPath && !this.refreshStage && !renderAsWireframe.value) {
        this.invalidPath.draw(ctx, false, 0, null);
        ctx.clip();
      }
      var bgcolor = this.root._color;
      if (bgcolor) {
        if (bgcolor.alpha < 255) {
          ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
        }
        if (bgcolor.alpha > 0) {
          ctx.fillStyle = rgbaObjToStr(bgcolor);
          if (this.invalidPath && !this.refreshStage && !renderAsWireframe.value) {
            ctx.fill();
          } else {
            ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
          }
        }
      }
      ctx.mozFillRule = 'evenodd';
    }
    this.depth++;
    if (this.clipDepth && this.clipDepth.length > 0) {
      this.clipStack = {
        depth: this.depth,
        clip: this.clipDepth,
        next: this.clipStack
      };
      this.clipDepth = null;
    }
  },
  childrenEnd: function (parent) {
    if (this.clipDepth) {
      while (this.clipDepth.length > 0) {
        var clipDepthInfo = this.clipDepth.pop();
        this.clipEnd(clipDepthInfo);
        this.ctx = clipDepthInfo.ctx;
      }
      this.clipDepth = null;
    }
    if (this.clipStack && this.clipStack.depth === this.depth) {
      this.clipDepth = this.clipStack.clip;
      this.clipStack = this.clipStack.next;
    }
    this.depth--;
    if (this.depth === 0) {
      this.ctx.restore();
      this.invalidPath = null;
    }
  },
  visit: function (child, visitContainer, context) {
    var ctx = this.ctx;
    var parentHasClippingMask = context.isClippingMask;
    var parentColorTransform = context.colorTransform;
    var clippingMask = parentHasClippingMask === true;
    if (child._cxform) {
      context.colorTransform = parentColorTransform.applyCXForm(child._cxform);
    }
    if (!clippingMask) {
      while (this.clipDepth && this.clipDepth.length > 0 && child._depth > this.clipDepth[0].clipDepth) {
        var clipDepthInfo = this.clipDepth.shift();
        this.clipEnd(clipDepthInfo);
        context.parentCtxs.shift();
        ctx = this.ctx = clipDepthInfo.ctx;
      }
      if (this.clipDepth && this.clipDepth.length > 0 && child._depth <= this.clipDepth[0].clipDepth) {
        ctx = this.ctx = this.clipDepth[0].maskee.ctx;
      }
      if (child._clipDepth) {
        context.isClippingMask = clippingMask = true;
        var clipDepthInfo = this.clipStart(child);
        if (!this.clipDepth) {
          this.clipDepth = [
            clipDepthInfo
          ];
        } else {
          this.clipDepth.unshift(clipDepthInfo);
        }
        context.parentCtxs.unshift(ctx);
        ctx = this.ctx = clipDepthInfo.mask.ctx;
      }
    }
    if (clippingMask && child._isContainer) {
      ctx.save();
      renderDisplayObject(child, ctx, context);
      for (var i = 0, n = child._children.length; i < n; i++) {
        var child1 = child._children[i];
        if (!child1) {
          continue;
        }
        if (this.ignoreVisibleAttribute || child1._visible && !child1._maskedObject) {
          this.visit(child1, visitContainer, context);
        }
      }
      ctx.restore();
      ctx.fill();
      context.isClippingMask = parentHasClippingMask;
      context.colorTransform = parentColorTransform;
      return;
    }
    ctx.save();
    ctx.globalCompositeOperation = getBlendModeName(child._blendMode);
    if (child._mask) {
      var clipInfo = this.clipStart(child);
      var mask = clipInfo.mask;
      var maskee = clipInfo.maskee;
      context.parentCtxs.push(ctx);
      var savedClipDepth = this.clipDepth;
      this.clipDepth = null;
      this.ctx = mask.ctx;
      this.visit(child._mask, visitContainer, new RenderingContext(this.refreshStage));
      this.ctx = ctx;
      this.clipDepth = savedClipDepth;
      renderDisplayObject(child, maskee.ctx, context);
      if (child._isContainer) {
        this.ctx = maskee.ctx;
        visitContainer(child, this, context);
        this.ctx = ctx;
      }
      context.parentCtxs.pop();
      this.clipEnd(clipInfo);
    } else {
      renderDisplayObject(child, ctx, context);
      if (child._isContainer) {
        visitContainer(child, this, context);
      }
    }
    ctx.restore();
    if (clippingMask) {
      ctx.fill();
    }
    context.isClippingMask = parentHasClippingMask;
    context.colorTransform = parentColorTransform;
  },
  clipStart: function (child) {
    var m = child._parent._getConcatenatedTransform(null, true);
    var tx = m.tx / 20;
    var ty = m.ty / 20;
    var mask = CanvasCache.getCanvas(this.ctx.canvas);
    mask.ctx.setTransform(m.a, m.b, m.c, m.d, tx, ty);
    var maskee = CanvasCache.getCanvas(this.ctx.canvas);
    maskee.ctx.setTransform(m.a, m.b, m.c, m.d, tx, ty);
    var clipInfo = {
        ctx: this.ctx,
        mask: mask,
        maskee: maskee,
        clipDepth: child._clipDepth
      };
    return clipInfo;
  },
  clipEnd: function (clipInfo) {
    var ctx = clipInfo.ctx;
    var mask = clipInfo.mask;
    var maskee = clipInfo.maskee;
    maskee.ctx.globalCompositeOperation = 'destination-in';
    maskee.ctx.setTransform(1, 0, 0, 1, 0, 0);
    maskee.ctx.drawImage(mask.canvas, 0, 0);
    ctx.save();
    ctx.setTransform(1, 0, 0, 1, 0, 0);
    ctx.drawImage(maskee.canvas, 0, 0);
    ctx.restore();
    CanvasCache.releaseCanvas(mask);
    CanvasCache.releaseCanvas(maskee);
  }
};
function RenderingColorTransform() {
  this.mode = null;
  this.transform = [
    1,
    1,
    1,
    1,
    0,
    0,
    0,
    0
  ];
}
RenderingColorTransform.prototype = {
  applyCXForm: function (cxform) {
    var t = this.transform;
    t = [
      t[0] * cxform.redMultiplier / 256,
      t[1] * cxform.greenMultiplier / 256,
      t[2] * cxform.blueMultiplier / 256,
      t[3] * cxform.alphaMultiplier / 256,
      t[4] * cxform.redMultiplier / 256 + cxform.redOffset,
      t[5] * cxform.greenMultiplier / 256 + cxform.greenOffset,
      t[6] * cxform.blueMultiplier / 256 + cxform.blueOffset,
      t[7] * cxform.alphaMultiplier / 256 + cxform.alphaOffset
    ];
    var mode;
    var PRECISION = 0.0001;
    if (Math.abs(t[0] - 1) < PRECISION && Math.abs(t[1] - 1) < PRECISION && Math.abs(t[2] - 1) < PRECISION && t[3] >= 0 && Math.abs(t[4]) < PRECISION && Math.abs(t[5]) < PRECISION && Math.abs(t[6]) < PRECISION && Math.abs(t[7]) < PRECISION) {
      mode = Math.abs(t[3] - 1) < PRECISION ? null : 'simple';
    } else {
      mode = 'complex';
    }
    var clone = Object.create(RenderingColorTransform.prototype);
    clone.mode = mode;
    clone.transform = t;
    return clone;
  },
  setFillStyle: function (ctx, style) {
    if (this.mode === 'complex') {
      style = typeof style === 'function' ? style(ctx, this) : this.convertColor(style);
    } else if (typeof style === 'number') {
      style = this.convertNumericColor(style);
    } else if (typeof style === 'function') {
      style = style.defaultFillStyle;
    }
    ctx.fillStyle = style;
  },
  setStrokeStyle: function (ctx, style) {
    if (this.mode === 'complex') {
      style = typeof style === 'function' ? style(ctx, this) : this.convertColor(style);
    } else if (typeof style === 'number') {
      style = this.convertNumericColor(style);
    } else if (typeof style === 'function') {
      style = style.defaultFillStyle;
    }
    ctx.strokeStyle = style;
  },
  addGradientColorStop: function (gradient, ratio, style) {
    if (this.mode === 'complex') {
      style = this.convertColor(style);
    } else if (typeof style === 'number') {
      style = this.convertNumericColor(style);
    }
    gradient.addColorStop(ratio, style);
  },
  setAlpha: function (ctx, force) {
    if (this.mode === 'simple' || force) {
      var t = this.transform;
      ctx.globalAlpha = Math.min(1, Math.max(0, ctx.globalAlpha * t[3]));
    }
  },
  convertNumericColor: function (num) {
    return '#' + (num | 16777216).toString(16).substr(1);
  },
  convertColor: function (style) {
    var t = this.transform;
    var m;
    switch (typeof style) {
    case 'string':
      if (style[0] === '#') {
        m = [
          undefined,
          parseInt(style.substr(1, 2), 16),
          parseInt(style.substr(3, 2), 16),
          parseInt(style.substr(5, 2), 16),
          1
        ];
      }
      m = m || /rgba\(([^,]+),([^,]+),([^,]+),([^)]+)\)/.exec(style);
      if (!m) {
        return style;
      }
      break;
    case 'number':
      m = [
        style,
        style >> 16 & 255,
        style >> 8 & 255,
        style & 255,
        1
      ];
      break;
    default:
      return style;
    }
    var r = Math.min(255, Math.max(0, m[1] * t[0] + t[4])) | 0;
    var g = Math.min(255, Math.max(0, m[2] * t[1] + t[5])) | 0;
    var b = Math.min(255, Math.max(0, m[3] * t[2] + t[6])) | 0;
    var a = Math.min(1, Math.max(0, m[4] * t[3] + t[7] / 256));
    return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
  },
  getTransformFingerprint: function () {
    return this.transform.join('|');
  }
};
function RenderingContext(refreshStage, invalidPath) {
  this.refreshStage = refreshStage === true;
  this.invalidPath = invalidPath;
  this.isClippingMask = false;
  this.colorTransform = new RenderingColorTransform();
  this.parentCtxs = [];
}
function renderDisplayObject(child, ctx, context) {
  var m = child._currentTransform;
  if (m) {
    ctx.transform(m.a, m.b, m.c, m.d, m.tx / 20, m.ty / 20);
  }
  if (!renderAsWireframe.value) {
    if (child._alpha !== 1) {
      ctx.globalAlpha *= child._alpha;
    }
    if (context.invalidPath && !child._invalid && !context.refreshStage) {
      return;
    }
    if (child._graphics) {
      var graphics = child._graphics;
      if (graphics._bitmap) {
        ctx.save();
        ctx.translate(child._bbox.xMin / 20, child._bbox.yMin / 20);
        context.colorTransform.setAlpha(ctx, true);
        ctx.drawImage(graphics._bitmap, 0, 0);
        ctx.restore();
      } else {
        var ratio = child.ratio;
        if (ratio === undefined) {
          ratio = 0;
        }
        graphics.draw(ctx, context.isClippingMask, ratio, context.colorTransform);
      }
    }
    if (child.draw) {
      child.draw(ctx, child.ratio, context.colorTransform, context.parentCtxs);
    }
  } else {
    if (!child._invalid && !context.refreshStage) {
      return;
    }
    if (child.getBounds) {
      var b = child.getBounds(null);
      if (b && b.xMax - b.xMin > 0 && b.yMax - b.yMin > 0) {
        if (!child._wireframeStrokeStyle) {
          child._wireframeStrokeStyle = randomStyle();
        }
        ctx.save();
        ctx.strokeStyle = child._wireframeStrokeStyle;
        var x = b.xMin / 20;
        var y = b.yMin / 20;
        ctx.strokeRect(x + 0.5, y + 0.5, b.xMax / 20 - x - 1, b.yMax / 20 - y - 1);
        ctx.restore();
      }
    }
  }
  child._invalid = false;
}
function renderQuadTree(ctx, qtree) {
  ctx.strokeRect(qtree.x / 20, qtree.y / 20, qtree.width / 20, qtree.height / 20);
  var nodes = qtree.nodes;
  for (var i = 0; i < nodes.length; i++) {
    renderQuadTree(ctx, nodes[i]);
  }
}
var renderingTerminated = false;
var samplesLeftPlusOne = 0;
function triggerSampling(count) {
  samplesLeftPlusOne = -count - 1;
}
function sampleStart() {
  if (!samplesLeftPlusOne) {
    return;
  }
  if (samplesLeftPlusOne < 0) {
    console.profile('Sample');
    samplesLeftPlusOne *= -1;
  }
  if (samplesLeftPlusOne > 0) {
    console.info('Sampling Frame: ' + (samplesLeftPlusOne - 1));
  }
}
function sampleEnd() {
  if (!samplesLeftPlusOne) {
    return;
  }
  samplesLeftPlusOne--;
  if (samplesLeftPlusOne === 1) {
    console.profileEnd('Sample');
  }
}
var timeline;
var hudTimeline;
function timelineEnter(name) {
  timeline && timeline.enter(name);
  hudTimeline && hudTimeline.enter(name);
}
function timelineLeave(name) {
  timeline && timeline.leave(name);
  hudTimeline && hudTimeline.leave(name);
}
function timelineWrapBroadcastMessage(domain, message) {
  timelineEnter(message);
  domain.broadcastMessage(message);
  timelineLeave(message);
}
function initializeHUD(stage, parentCanvas) {
  var canvas = document.createElement('canvas');
  var canvasContainer = document.createElement('div');
  canvasContainer.appendChild(canvas);
  canvasContainer.style.position = 'absolute';
  canvasContainer.style.top = '0px';
  canvasContainer.style.left = '0px';
  canvasContainer.style.width = '100%';
  canvasContainer.style.height = '150px';
  canvasContainer.style.backgroundColor = 'rgba(0, 0, 0, 0.4)';
  canvasContainer.style.pointerEvents = 'none';
  parentCanvas.parentElement.appendChild(canvasContainer);
  hudTimeline = new Timeline(canvas);
  hudTimeline.setFrameRate(stage._frameRate);
  hudTimeline.refreshEvery(10);
}
function createRenderDummyBalls(ctx, stage) {
  var dummyBalls;
  var radius = 10;
  var speed = 1;
  var m = stage._concatenatedTransform;
  var scaleX = m.a, scaleY = m.d;
  dummyBalls = [];
  for (var i = 0; i < 10; i++) {
    dummyBalls.push({
      position: {
        x: radius + Math.random() * ((ctx.canvas.width - 2 * radius) / scaleX),
        y: radius + Math.random() * ((ctx.canvas.height - 2 * radius) / scaleY)
      },
      velocity: {
        x: speed * (Math.random() - 0.5),
        y: speed * (Math.random() - 0.5)
      }
    });
  }
  ctx.fillStyle = 'black';
  ctx.lineWidth = 2;
  ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  return function renderDummyBalls() {
    ctx.fillStyle = 'black';
    ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    ctx.strokeStyle = 'green';
    dummyBalls.forEach(function (ball) {
      var position = ball.position;
      var velocity = ball.velocity;
      ctx.beginPath();
      ctx.arc(position.x, position.y, radius, 0, Math.PI * 2, true);
      ctx.stroke();
      var x = position.x + velocity.x;
      var y = position.y + velocity.y;
      if (x < radius || x > ctx.canvas.width / scaleX - radius) {
        velocity.x *= -1;
      }
      if (y < radius || y > ctx.canvas.height / scaleY - radius) {
        velocity.y *= -1;
      }
      position.x += velocity.x;
      position.y += velocity.y;
    });
  };
}
function renderStage(stage, ctx, events) {
  var frameWidth, frameHeight;
  if (!timeline && hud.value) {
    initializeHUD(stage, ctx.canvas);
  }
  function updateRenderTransform() {
    frameWidth = ctx.canvas.width;
    frameHeight = ctx.canvas.height;
    var scaleX = frameWidth / stage._stageWidth * 20;
    var scaleY = frameHeight / stage._stageHeight * 20;
    switch (stage._scaleMode) {
    case 'exactFit':
      break;
    case 'noBorder':
      if (scaleX > scaleY) {
        scaleY = scaleX;
      } else {
        scaleX = scaleY;
      }
      break;
    case 'noScale':
      var pixelRatio = ctx.canvas._pixelRatio || 1;
      scaleX = pixelRatio;
      scaleY = pixelRatio;
      break;
    case 'showAll':
      if (scaleX < scaleY) {
        scaleY = scaleX;
      } else {
        scaleX = scaleY;
      }
      break;
    }
    var align = stage._align;
    var offsetX, offsetY;
    if (align.indexOf('L') >= 0) {
      offsetX = 0;
    } else if (align.indexOf('R') >= 0) {
      offsetX = frameWidth - scaleX * stage._stageWidth / 20;
    } else {
      offsetX = (frameWidth - scaleX * stage._stageWidth / 20) / 2;
    }
    if (align.indexOf('T') >= 0) {
      offsetY = 0;
    } else if (align.indexOf('B') >= 0) {
      offsetY = frameHeight - scaleY * stage._stageHeight / 20;
    } else {
      offsetY = (frameHeight - scaleY * stage._stageHeight / 20) / 2;
    }
    ctx.setTransform(scaleX, 0, 0, scaleY, offsetX, offsetY);
    var m = stage._concatenatedTransform;
    m.a = scaleX;
    m.d = scaleY;
    m.tx = offsetX * 20;
    m.ty = offsetY * 20;
  }
  updateRenderTransform();
  var frameScheduler = new FrameScheduler();
  stage._frameScheduler = frameScheduler;
  var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || window.setTimeout;
  var renderDummyBalls = dummyAnimation.value && createRenderDummyBalls(ctx, stage);
  console.timeEnd('Initialize Renderer');
  console.timeEnd('Total');
  var firstRun = true;
  var frameCount = 0;
  var frameFPSAverage = new Shumway.Metrics.Average(120);
  var frameRequested = true;
  function drawFrame(renderFrame, repaint) {
    sampleStart();
    var refreshStage = false;
    if (stage._invalid) {
      updateRenderTransform();
      stage._invalid = false;
      refreshStage = true;
    }
    var mouseMoved = false;
    if (stage._mouseMoved) {
      stage._mouseMoved = false;
      mouseMoved = stage._mouseOver;
    } else {
      stage._handleMouseButtons();
    }
    if (renderFrame || refreshStage || mouseMoved) {
      FrameCounter.clear();
      var frameStartTime = performance.now();
      timelineEnter('frame');
      traceRenderer.value && appendToFrameTerminal('Begin Frame #' + frameCount++, 'purple');
      var domain = avm2.systemDomain;
      if (renderFrame) {
        timelineEnter('events');
        if (firstRun) {
          firstRun = false;
        } else {
          enableAdvanceFrame.value && timelineWrapBroadcastMessage(domain, 'advanceFrame');
          enableEnterFrame.value && timelineWrapBroadcastMessage(domain, 'enterFrame');
          enableConstructChildren.value && timelineWrapBroadcastMessage(domain, 'constructChildren');
        }
        timelineWrapBroadcastMessage(domain, 'frameConstructed');
        timelineWrapBroadcastMessage(domain, 'executeFrame');
        timelineWrapBroadcastMessage(domain, 'exitFrame');
        timelineLeave('events');
      }
      if (stage._deferRenderEvent) {
        stage._deferRenderEvent = false;
        domain.broadcastMessage('render', 'render');
      }
      var drawEnabled = isCanvasVisible(ctx.canvas) && (refreshStage || renderFrame) && (frameRequested || repaint || !skipFrameDraw.value);
      if (drawEnabled && !repaint && skipFrameDraw.value && frameScheduler.shallSkipDraw) {
        drawEnabled = false;
        frameScheduler.skipDraw();
        traceRenderer.value && appendToFrameTerminal('Skip Frame Draw', 'red');
      }
      if (drawEnabled) {
        frameScheduler.startDraw();
        var invalidPath = null;
        traceRenderer.value && frameWriter.enter('> Invalidation');
        timelineEnter('invalidate');
        invalidPath = stage._processInvalidations(refreshStage);
        timelineLeave('invalidate');
        traceRenderer.value && frameWriter.leave('< Invalidation');
        if (!disableRenderVisitor.value && !invalidPath.isEmpty) {
          timelineEnter('render');
          traceRenderer.value && frameWriter.enter('> Rendering');
          new RenderVisitor(stage, ctx, invalidPath, refreshStage).start();
          traceRenderer.value && frameWriter.leave('< Rendering');
          timelineLeave('render');
        }
        if (showQuadTree.value) {
          ctx.strokeStyle = 'green';
          renderQuadTree(ctx, stage._qtree);
        }
        if (invalidPath && !refreshStage && showRedrawRegions.value) {
          ctx.strokeStyle = 'red';
          invalidPath.draw(ctx);
          ctx.stroke();
        }
        frameScheduler.endDraw();
      }
      if (mouseMoved && !disableMouseVisitor.value) {
        renderFrame && timelineEnter('mouse');
        traceRenderer.value && frameWriter.enter('> Mouse Handling');
        stage._handleMouse();
        traceRenderer.value && frameWriter.leave('< Mouse Handling');
        renderFrame && timelineLeave('mouse');
        ctx.canvas.style.cursor = stage._cursor;
      }
      if (traceRenderer.value) {
        frameWriter.enter('> Frame Counters');
        for (var name in FrameCounter.counts) {
          frameWriter.writeLn(name + ': ' + FrameCounter.counts[name]);
        }
        frameWriter.leave('< Frame Counters');
        var frameElapsedTime = performance.now() - frameStartTime;
        var frameFPS = 1000 / frameElapsedTime;
        frameFPSAverage.push(frameFPS);
        traceRenderer.value && appendToFrameTerminal('End Frame Time: ' + frameElapsedTime.toFixed(2) + ' (' + frameFPS.toFixed(2) + ' fps, ' + frameFPSAverage.average().toFixed(2) + ' average fps)', 'purple');
      }
      timelineLeave('frame');
    } else {
      traceRenderer.value && appendToFrameTerminal('Skip Frame', 'black');
    }
    sampleEnd();
  }
  (function draw() {
    var renderFrame = true;
    if (events.onBeforeFrame) {
      var e = {
          cancel: false
        };
      events.onBeforeFrame(e);
      renderFrame = !e.cancel;
    }
    if (renderDummyBalls) {
      if (renderFrame) {
        renderDummyBalls();
        events.onAfterFrame && events.onAfterFrame();
      }
      setTimeout(draw);
      return;
    }
    frameScheduler.startFrame(stage._frameRate);
    drawFrame(renderFrame, false);
    frameScheduler.endFrame();
    frameRequested = false;
    if (!frameScheduler.isOnTime) {
      traceRenderer.value && appendToFrameTerminal('Frame Is Late', 'red');
    }
    if (renderFrame && events.onAfterFrame) {
      events.onAfterFrame();
    }
    if (renderingTerminated) {
      if (events.onTerminated) {
        events.onTerminated();
      }
      return;
    }
    setTimeout(draw, turboMode.value ? 0 : frameScheduler.nextFrameIn);
  }());
  (function frame() {
    if (renderingTerminated) {
      return;
    }
    frameRequested = true;
    if ((stage._invalid || stage._mouseMoved) && !renderDummyBalls) {
      drawFrame(false, true);
    }
    requestAnimationFrame(frame);
  }());
}
var FrameScheduler = function () {
    var STATS_TO_REMEMBER = 50;
    var MAX_DRAWS_TO_SKIP = 2;
    var INTERVAL_PADDING_MS = 4;
    var SPEED_ADJUST_RATE = 0.9;
    function FrameScheduler() {
      this._drawStats = [];
      this._drawStatsSum = 0;
      this._drawStarted = 0;
      this._drawsSkipped = 0;
      this._expectedNextFrameAt = performance.now();
      this._onTime = true;
      this._trackDelta = false;
      this._delta = 0;
      this._onTimeDelta = 0;
    }
    FrameScheduler.prototype = {
      get shallSkipDraw() {
        if (this._drawsSkipped >= MAX_DRAWS_TO_SKIP) {
          return false;
        }
        var averageDraw = this._drawStats.length < STATS_TO_REMEMBER ? 0 : this._drawStatsSum / this._drawStats.length;
        var estimatedDrawEnd = performance.now() + averageDraw;
        return estimatedDrawEnd + INTERVAL_PADDING_MS > this._expectedNextFrameAt;
      },
      get nextFrameIn() {
        return Math.max(0, this._expectedNextFrameAt - performance.now());
      },
      get isOnTime() {
        return this._onTime;
      },
      startFrame: function (frameRate) {
        var interval = 1000 / frameRate;
        var adjustedInterval = interval;
        var delta = this._onTimeDelta + this._delta;
        if (delta !== 0) {
          if (delta < 0) {
            adjustedInterval *= SPEED_ADJUST_RATE;
          } else if (delta > 0) {
            adjustedInterval /= SPEED_ADJUST_RATE;
          }
          this._onTimeDelta += interval - adjustedInterval;
        }
        this._expectedNextFrameAt += adjustedInterval;
        this._onTime = true;
      },
      endFrame: function () {
        var estimatedNextFrameStart = performance.now() + INTERVAL_PADDING_MS;
        if (estimatedNextFrameStart > this._expectedNextFrameAt) {
          if (this._trackDelta) {
            this._onTimeDelta += this._expectedNextFrameAt - estimatedNextFrameStart;
            console.log(this._onTimeDelta);
          }
          this._expectedNextFrameAt = estimatedNextFrameStart;
          this._onTime = false;
        }
      },
      startDraw: function () {
        this._drawsSkipped = 0;
        this._drawStarted = performance.now();
      },
      endDraw: function () {
        var drawTime = performance.now() - this._drawStarted;
        this._drawStats.push(drawTime);
        this._drawStatsSum += drawTime;
        while (this._drawStats.length > STATS_TO_REMEMBER) {
          this._drawStatsSum -= this._drawStats.shift();
        }
      },
      skipDraw: function () {
        this._drawsSkipped++;
      },
      setDelta: function (value) {
        if (!this._trackDelta) {
          return;
        }
        this._delta = value;
      },
      startTrackDelta: function () {
        this._trackDelta = true;
      },
      endTrackDelta: function () {
        if (!this._trackDelta) {
          return;
        }
        this._trackDelta = false;
        this._delta = 0;
        this._onTimeDelta = 0;
      }
    };
    return FrameScheduler;
  }();
var tagHandler = function (global) {
    function defineShape($bytes, $stream, $, swfVersion, tagCode) {
      $ || ($ = {});
      $.id = readUi16($bytes, $stream);
      var $0 = $.bbox = {};
      bbox($bytes, $stream, $0, swfVersion, tagCode);
      var isMorph = $.isMorph = tagCode === 46 || tagCode === 84;
      if (isMorph) {
        var $1 = $.bboxMorph = {};
        bbox($bytes, $stream, $1, swfVersion, tagCode);
      }
      var hasStrokes = $.hasStrokes = tagCode === 83 || tagCode === 84;
      if (hasStrokes) {
        var $2 = $.strokeBbox = {};
        bbox($bytes, $stream, $2, swfVersion, tagCode);
        if (isMorph) {
          var $3 = $.strokeBboxMorph = {};
          bbox($bytes, $stream, $3, swfVersion, tagCode);
        }
        var reserved = readUb($bytes, $stream, 5);
        $.fillWinding = readUb($bytes, $stream, 1);
        $.nonScalingStrokes = readUb($bytes, $stream, 1);
        $.scalingStrokes = readUb($bytes, $stream, 1);
      }
      if (isMorph) {
        $.offsetMorph = readUi32($bytes, $stream);
        morphShapeWithStyle($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes);
      } else {
        shapeWithStyle($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes);
      }
      return $;
    }
    function placeObject($bytes, $stream, $, swfVersion, tagCode) {
      var flags, hasEvents, clip, hasName, hasRatio, hasCxform, hasMatrix, place;
      var move, hasBackgroundColor, hasVisibility, hasImage, hasClassName, cache;
      var blend, hasFilters, eoe;
      $ || ($ = {});
      if (tagCode > 4) {
        if (tagCode > 26) {
          flags = readUi16($bytes, $stream);
        } else {
          flags = readUi8($bytes, $stream);
        }
        hasEvents = $.hasEvents = flags >> 7 & 1;
        clip = $.clip = flags >> 6 & 1;
        hasName = $.hasName = flags >> 5 & 1;
        hasRatio = $.hasRatio = flags >> 4 & 1;
        hasCxform = $.hasCxform = flags >> 3 & 1;
        hasMatrix = $.hasMatrix = flags >> 2 & 1;
        place = $.place = flags >> 1 & 1;
        move = $.move = flags & 1;
        if (tagCode === 70) {
          hasBackgroundColor = $.hasBackgroundColor = flags >> 15 & 1;
          hasVisibility = $.hasVisibility = flags >> 14 & 1;
          hasImage = $.hasImage = flags >> 12 & 1;
          hasClassName = $.hasClassName = flags >> 11 & 1;
          cache = $.cache = flags >> 10 & 1;
          blend = $.blend = flags >> 9 & 1;
          hasFilters = $.hasFilters = flags >> 8 & 1;
        } else {
          cache = $.cache = 0;
          blend = $.blend = 0;
          hasFilters = $.hasFilters = 0;
        }
        $.depth = readUi16($bytes, $stream);
        if (hasClassName) {
          $.className = readString($bytes, $stream, 0);
        }
        if (place) {
          $.symbolId = readUi16($bytes, $stream);
        }
        if (hasMatrix) {
          var $0 = $.matrix = {};
          matrix($bytes, $stream, $0, swfVersion, tagCode);
        }
        if (hasCxform) {
          var $1 = $.cxform = {};
          cxform($bytes, $stream, $1, swfVersion, tagCode);
        }
        if (hasRatio) {
          $.ratio = readUi16($bytes, $stream);
        }
        if (hasName) {
          $.name = readString($bytes, $stream, 0);
        }
        if (clip) {
          $.clipDepth = readUi16($bytes, $stream);
        }
        if (hasFilters) {
          var count = readUi8($bytes, $stream);
          var $2 = $.filters = [];
          var $3 = count;
          while ($3--) {
            var $4 = {};
            anyFilter($bytes, $stream, $4, swfVersion, tagCode);
            $2.push($4);
          }
        }
        if (blend) {
          $.blendMode = readUi8($bytes, $stream);
        }
        if (cache) {
          $.bmpCache = readUi8($bytes, $stream);
        }
        if (hasEvents) {
          var reserved = readUi16($bytes, $stream);
          if (swfVersion >= 6) {
            var allFlags = readUi32($bytes, $stream);
          } else {
            var allFlags = readUi16($bytes, $stream);
          }
          var $28 = $.events = [];
          do {
            var $29 = {};
            var temp = events($bytes, $stream, $29, swfVersion, tagCode);
            eoe = temp.eoe;
            $28.push($29);
          } while (!eoe);
        }
        if (hasBackgroundColor) {
          var $126 = $.backgroundColor = {};
          argb($bytes, $stream, $126, swfVersion, tagCode);
        }
        if (hasVisibility) {
          $.visibility = readUi8($bytes, $stream);
        }
      } else {
        $.place = 1;
        $.symbolId = readUi16($bytes, $stream);
        $.depth = readUi16($bytes, $stream);
        $.hasMatrix = 1;
        var $30 = $.matrix = {};
        matrix($bytes, $stream, $30, swfVersion, tagCode);
        if ($stream.remaining()) {
          $.hasCxform = 1;
          var $31 = $.cxform = {};
          cxform($bytes, $stream, $31, swfVersion, tagCode);
        }
      }
      return $;
    }
    function removeObject($bytes, $stream, $, swfVersion, tagCode) {
      $ || ($ = {});
      if (tagCode === 5) {
        $.symbolId = readUi16($bytes, $stream);
      }
      $.depth = readUi16($bytes, $stream);
      return $;
    }
    function defineImage($bytes, $stream, $, swfVersion, tagCode) {
      var imgData;
      $ || ($ = {});
      $.id = readUi16($bytes, $stream);
      if (tagCode > 21) {
        var alphaDataOffset = readUi32($bytes, $stream);
        if (tagCode === 90) {
          $.deblock = readFixed8($bytes, $stream);
        }
        imgData = $.imgData = readBinary($bytes, $stream, alphaDataOffset);
        $.alphaData = readBinary($bytes, $stream, 0);
      } else {
        imgData = $.imgData = readBinary($bytes, $stream, 0);
      }
      switch (imgData[0] << 8 | imgData[1]) {
      case 65496:
      case 65497:
        $.mimeType = 'image/jpeg';
        break;
      case 35152:
        $.mimeType = 'image/png';
        break;
      case 18249:
        $.mimeType = 'image/gif';
        break;
      default:
        $.mimeType = 'application/octet-stream';
      }
      if (tagCode === 6) {
        $.incomplete = 1;
      }
      return $;
    }
    function defineButton($bytes, $stream, $, swfVersion, tagCode) {
      var eob, hasFilters, count, blend;
      $ || ($ = {});
      $.id = readUi16($bytes, $stream);
      if (tagCode == 7) {
        var $0 = $.characters = [];
        do {
          var $1 = {};
          var temp = button($bytes, $stream, $1, swfVersion, tagCode);
          eob = temp.eob;
          $0.push($1);
        } while (!eob);
        $.actionsData = readBinary($bytes, $stream, 0);
      } else {
        var trackFlags = readUi8($bytes, $stream);
        $.trackAsMenu = trackFlags >> 7 & 1;
        var actionOffset = readUi16($bytes, $stream);
        var $28 = $.characters = [];
        do {
          var $29 = {};
          var flags = readUi8($bytes, $stream);
          var eob = $29.eob = !flags;
          if (swfVersion >= 8) {
            blend = $29.blend = flags >> 5 & 1;
            hasFilters = $29.hasFilters = flags >> 4 & 1;
          } else {
            blend = $29.blend = 0;
            hasFilters = $29.hasFilters = 0;
          }
          $29.stateHitTest = flags >> 3 & 1;
          $29.stateDown = flags >> 2 & 1;
          $29.stateOver = flags >> 1 & 1;
          $29.stateUp = flags & 1;
          if (!eob) {
            $29.symbolId = readUi16($bytes, $stream);
            $29.depth = readUi16($bytes, $stream);
            var $30 = $29.matrix = {};
            matrix($bytes, $stream, $30, swfVersion, tagCode);
            if (tagCode === 34) {
              var $31 = $29.cxform = {};
              cxform($bytes, $stream, $31, swfVersion, tagCode);
            }
            if (hasFilters) {
              var count = readUi8($bytes, $stream);
              var $2 = $.filters = [];
              var $3 = count;
              while ($3--) {
                var $4 = {};
                anyFilter($bytes, $stream, $4, swfVersion, tagCode);
                $2.push($4);
              }
            }
            if (blend) {
              $29.blendMode = readUi8($bytes, $stream);
            }
          }
          $28.push($29);
        } while (!eob);
        if (!(!actionOffset)) {
          var $56 = $.buttonActions = [];
          do {
            var $57 = {};
            buttonCondAction($bytes, $stream, $57, swfVersion, tagCode);
            $56.push($57);
          } while ($stream.remaining() > 0);
        }
      }
      return $;
    }
    function defineJPEGTables($bytes, $stream, $, swfVersion, tagCode) {
      $ || ($ = {});
      $.id = 0;
      $.imgData = readBinary($bytes, $stream, 0);
      $.mimeType = 'application/octet-stream';
      return $;
    }
    function setBackgroundColor($bytes, $stream, $, swfVersion, tagCode) {
      $ || ($ = {});
      var $0 = $.color = {};
      rgb($bytes, $stream, $0, swfVersion, tagCode);
      return $;
    }
    function defineBinaryData($bytes, $stream, $, swfVersion, tagCode) {
      $ || ($ = {});
      $.id = readUi16($bytes, $stream);
      var reserved = readUi32($bytes, $stream);
      $.data = readBinary($bytes, $stream, 0);
      return $;
    }
    function defineFont($bytes, $stream, $, swfVersion, tagCode) {
      $ || ($ = {});
      $.id = readUi16($bytes, $stream);
      var firstOffset = readUi16($bytes, $stream);
      var glyphCount = $.glyphCount = firstOffset / 2;
      var restOffsets = [];
      var $0 = glyphCount - 1;
      while ($0--) {
        restOffsets.push(readUi16($bytes, $stream));
      }
      $.offsets = [
        firstOffset
      ].concat(restOffsets);
      var $1 = $.glyphs = [];
      var $2 = glyphCount;
      while ($2--) {
        var $3 = {};
        shape($bytes, $stream, $3, swfVersion, tagCode);
        $1.push($3);
      }
      return $;
    }
    function defineLabel($bytes, $stream, $, swfVersion, tagCode) {
      var eot;
      $ || ($ = {});
      $.id = readUi16($bytes, $stream);
      var $0 = $.bbox = {};
      bbox($bytes, $stream, $0, swfVersion, tagCode);
      var $1 = $.matrix = {};
      matrix($bytes, $stream, $1, swfVersion, tagCode);
      var glyphBits = $.glyphBits = readUi8($bytes, $stream);
      var advanceBits = $.advanceBits = readUi8($bytes, $stream);
      var $2 = $.records = [];
      do {
        var $3 = {};
        var temp = textRecord($bytes, $stream, $3, swfVersion, tagCode, glyphBits, advanceBits);
        eot = temp.eot;
        $2.push($3);
      } while (!eot);
      return $;
    }
    function doAction($bytes, $stream, $, swfVersion, tagCode) {
      $ || ($ = {});
      if (tagCode === 59) {
        $.spriteId = readUi16($bytes, $stream);
      }
      $.actionsData = readBinary($bytes, $stream, 0);
      return $;
    }
    function defineSound($bytes, $stream, $, swfVersion, tagCode) {
      $ || ($ = {});
      $.id = readUi16($bytes, $stream);
      var soundFlags = readUi8($bytes, $stream);
      $.soundFormat = soundFlags >> 4 & 15;
      $.soundRate = soundFlags >> 2 & 3;
      $.soundSize = soundFlags >> 1 & 1;
      $.soundType = soundFlags & 1;
      $.samplesCount = readUi32($bytes, $stream);
      $.soundData = readBinary($bytes, $stream, 0);
      return $;
    }
    function startSound($bytes, $stream, $, swfVersion, tagCode) {
      $ || ($ = {});
      if (tagCode == 15) {
        $.soundId = readUi16($bytes, $stream);
      }
      if (tagCode == 89) {
        $.soundClassName = readString($bytes, $stream, 0);
      }
      var $0 = $.soundInfo = {};
      soundInfo($bytes, $stream, $0, swfVersion, tagCode);
      return $;
    }
    function soundStreamHead($bytes, $stream, $, swfVersion, tagCode) {
      $ || ($ = {});
      var playbackFlags = readUi8($bytes, $stream);
      $.playbackRate = playbackFlags >> 2 & 3;
      $.playbackSize = playbackFlags >> 1 & 1;
      $.playbackType = playbackFlags & 1;
      var streamFlags = readUi8($bytes, $stream);
      var streamCompression = $.streamCompression = streamFlags >> 4 & 15;
      $.streamRate = streamFlags >> 2 & 3;
      $.streamSize = streamFlags >> 1 & 1;
      $.streamType = streamFlags & 1;
      $.samplesCount = readUi32($bytes, $stream);
      if (streamCompression == 2) {
        $.latencySeek = readSi16($bytes, $stream);
      }
      return $;
    }
    function soundStreamBlock($bytes, $stream, $, swfVersion, tagCode) {
      $ || ($ = {});
      $.data = readBinary($bytes, $stream, 0);
      return $;
    }
    function defineBitmap($bytes, $stream, $, swfVersion, tagCode) {
      $ || ($ = {});
      $.id = readUi16($bytes, $stream);
      var format = $.format = readUi8($bytes, $stream);
      $.width = readUi16($bytes, $stream);
      $.height = readUi16($bytes, $stream);
      $.hasAlpha = tagCode === 36;
      if (format === 3) {
        $.colorTableSize = readUi8($bytes, $stream);
      }
      $.bmpData = readBinary($bytes, $stream, 0);
      return $;
    }
    function defineText($bytes, $stream, $, swfVersion, tagCode) {
      $ || ($ = {});
      $.id = readUi16($bytes, $stream);
      var $0 = $.bbox = {};
      bbox($bytes, $stream, $0, swfVersion, tagCode);
      var flags = readUi16($bytes, $stream);
      var hasText = $.hasText = flags >> 7 & 1;
      $.wordWrap = flags >> 6 & 1;
      $.multiline = flags >> 5 & 1;
      $.password = flags >> 4 & 1;
      $.readonly = flags >> 3 & 1;
      var hasColor = $.hasColor = flags >> 2 & 1;
      var hasMaxLength = $.hasMaxLength = flags >> 1 & 1;
      var hasFont = $.hasFont = flags & 1;
      var hasFontClass = $.hasFontClass = flags >> 15 & 1;
      $.autoSize = flags >> 14 & 1;
      var hasLayout = $.hasLayout = flags >> 13 & 1;
      $.noSelect = flags >> 12 & 1;
      $.border = flags >> 11 & 1;
      $.wasStatic = flags >> 10 & 1;
      $.html = flags >> 9 & 1;
      $.useOutlines = flags >> 8 & 1;
      if (hasFont) {
        $.fontId = readUi16($bytes, $stream);
      }
      if (hasFontClass) {
        $.fontClass = readString($bytes, $stream, 0);
      }
      if (hasFont) {
        $.fontHeight = readUi16($bytes, $stream);
      }
      if (hasColor) {
        var $1 = $.color = {};
        rgba($bytes, $stream, $1, swfVersion, tagCode);
      }
      if (hasMaxLength) {
        $.maxLength = readUi16($bytes, $stream);
      }
      if (hasLayout) {
        $.align = readUi8($bytes, $stream);
        $.leftMargin = readUi16($bytes, $stream);
        $.rightMargin = readUi16($bytes, $stream);
        $.indent = readSi16($bytes, $stream);
        $.leading = readSi16($bytes, $stream);
      }
      $.variableName = readString($bytes, $stream, 0);
      if (hasText) {
        $.initialText = readString($bytes, $stream, 0);
      }
      return $;
    }
    function frameLabel($bytes, $stream, $, swfVersion, tagCode) {
      $ || ($ = {});
      $.name = readString($bytes, $stream, 0);
      return $;
    }
    function defineFont2($bytes, $stream, $, swfVersion, tagCode) {
      $ || ($ = {});
      $.id = readUi16($bytes, $stream);
      var hasLayout = $.hasLayout = readUb($bytes, $stream, 1);
      if (swfVersion > 5) {
        $.shiftJis = readUb($bytes, $stream, 1);
      } else {
        var reserved = readUb($bytes, $stream, 1);
      }
      $.smallText = readUb($bytes, $stream, 1);
      $.ansi = readUb($bytes, $stream, 1);
      var wideOffset = $.wideOffset = readUb($bytes, $stream, 1);
      var wide = $.wide = readUb($bytes, $stream, 1);
      $.italic = readUb($bytes, $stream, 1);
      $.bold = readUb($bytes, $stream, 1);
      if (swfVersion > 5) {
        $.language = readUi8($bytes, $stream);
      } else {
        var reserved = readUi8($bytes, $stream);
        $.language = 0;
      }
      var nameLength = readUi8($bytes, $stream);
      $.name = readString($bytes, $stream, nameLength);
      if (tagCode === 75) {
        $.resolution = 20;
      }
      var glyphCount = $.glyphCount = readUi16($bytes, $stream);
      if (wideOffset) {
        var $0 = $.offsets = [];
        var $1 = glyphCount;
        while ($1--) {
          $0.push(readUi32($bytes, $stream));
        }
        $.mapOffset = readUi32($bytes, $stream);
      } else {
        var $2 = $.offsets = [];
        var $3 = glyphCount;
        while ($3--) {
          $2.push(readUi16($bytes, $stream));
        }
        $.mapOffset = readUi16($bytes, $stream);
      }
      var $4 = $.glyphs = [];
      var $5 = glyphCount;
      while ($5--) {
        var $6 = {};
        shape($bytes, $stream, $6, swfVersion, tagCode);
        $4.push($6);
      }
      if (wide) {
        var $47 = $.codes = [];
        var $48 = glyphCount;
        while ($48--) {
          $47.push(readUi16($bytes, $stream));
        }
      } else {
        var $49 = $.codes = [];
        var $50 = glyphCount;
        while ($50--) {
          $49.push(readUi8($bytes, $stream));
        }
      }
      if (hasLayout) {
        $.ascent = readUi16($bytes, $stream);
        $.descent = readUi16($bytes, $stream);
        $.leading = readSi16($bytes, $stream);
        var $51 = $.advance = [];
        var $52 = glyphCount;
        while ($52--) {
          $51.push(readSi16($bytes, $stream));
        }
        var $53 = $.bbox = [];
        var $54 = glyphCount;
        while ($54--) {
          var $55 = {};
          bbox($bytes, $stream, $55, swfVersion, tagCode);
          $53.push($55);
        }
        var kerningCount = readUi16($bytes, $stream);
        var $56 = $.kerning = [];
        var $57 = kerningCount;
        while ($57--) {
          var $58 = {};
          kerning($bytes, $stream, $58, swfVersion, tagCode, wide);
          $56.push($58);
        }
      }
      return $;
    }
    function fileAttributes($bytes, $stream, $, swfVersion, tagCode) {
      $ || ($ = {});
      var reserved = readUb($bytes, $stream, 1);
      $.useDirectBlit = readUb($bytes, $stream, 1);
      $.useGpu = readUb($bytes, $stream, 1);
      $.hasMetadata = readUb($bytes, $stream, 1);
      $.doAbc = readUb($bytes, $stream, 1);
      $.noCrossDomainCaching = readUb($bytes, $stream, 1);
      $.relativeUrls = readUb($bytes, $stream, 1);
      $.network = readUb($bytes, $stream, 1);
      var pad = readUb($bytes, $stream, 24);
      return $;
    }
    function doABC($bytes, $stream, $, swfVersion, tagCode) {
      $ || ($ = {});
      if (tagCode === 82) {
        $.flags = readUi32($bytes, $stream);
      } else {
        $.flags = 0;
      }
      if (tagCode === 82) {
        $.name = readString($bytes, $stream, 0);
      } else {
        $.name = '';
      }
      $.data = readBinary($bytes, $stream, 0);
      return $;
    }
    function exportAssets($bytes, $stream, $, swfVersion, tagCode) {
      $ || ($ = {});
      var exportsCount = readUi16($bytes, $stream);
      var $0 = $.exports = [];
      var $1 = exportsCount;
      while ($1--) {
        var $2 = {};
        $2.symbolId = readUi16($bytes, $stream);
        $2.className = readString($bytes, $stream, 0);
        $0.push($2);
      }
      return $;
    }
    function symbolClass($bytes, $stream, $, swfVersion, tagCode) {
      $ || ($ = {});
      var symbolCount = readUi16($bytes, $stream);
      var $0 = $.exports = [];
      var $1 = symbolCount;
      while ($1--) {
        var $2 = {};
        $2.symbolId = readUi16($bytes, $stream);
        $2.className = readString($bytes, $stream, 0);
        $0.push($2);
      }
      return $;
    }
    function defineScalingGrid($bytes, $stream, $, swfVersion, tagCode) {
      $ || ($ = {});
      $.symbolId = readUi16($bytes, $stream);
      var $0 = $.splitter = {};
      bbox($bytes, $stream, $0, swfVersion, tagCode);
      return $;
    }
    function defineScene($bytes, $stream, $, swfVersion, tagCode) {
      $ || ($ = {});
      var sceneCount = readEncodedU32($bytes, $stream);
      var $0 = $.scenes = [];
      var $1 = sceneCount;
      while ($1--) {
        var $2 = {};
        $2.offset = readEncodedU32($bytes, $stream);
        $2.name = readString($bytes, $stream, 0);
        $0.push($2);
      }
      var labelCount = readEncodedU32($bytes, $stream);
      var $3 = $.labels = [];
      var $4 = labelCount;
      while ($4--) {
        var $5 = {};
        $5.frame = readEncodedU32($bytes, $stream);
        $5.name = readString($bytes, $stream, 0);
        $3.push($5);
      }
      return $;
    }
    function bbox($bytes, $stream, $, swfVersion, tagCode) {
      align($bytes, $stream);
      var bits = readUb($bytes, $stream, 5);
      var xMin = readSb($bytes, $stream, bits);
      var xMax = readSb($bytes, $stream, bits);
      var yMin = readSb($bytes, $stream, bits);
      var yMax = readSb($bytes, $stream, bits);
      $.xMin = xMin;
      $.xMax = xMax;
      $.yMin = yMin;
      $.yMax = yMax;
      align($bytes, $stream);
    }
    function rgb($bytes, $stream, $, swfVersion, tagCode) {
      $.red = readUi8($bytes, $stream);
      $.green = readUi8($bytes, $stream);
      $.blue = readUi8($bytes, $stream);
      $.alpha = 255;
      return;
    }
    function rgba($bytes, $stream, $, swfVersion, tagCode) {
      $.red = readUi8($bytes, $stream);
      $.green = readUi8($bytes, $stream);
      $.blue = readUi8($bytes, $stream);
      $.alpha = readUi8($bytes, $stream);
      return;
    }
    function argb($bytes, $stream, $, swfVersion, tagCode) {
      $.alpha = readUi8($bytes, $stream);
      $.red = readUi8($bytes, $stream);
      $.green = readUi8($bytes, $stream);
      $.blue = readUi8($bytes, $stream);
    }
    function fillSolid($bytes, $stream, $, swfVersion, tagCode, isMorph) {
      if (tagCode > 22 || isMorph) {
        var $125 = $.color = {};
        rgba($bytes, $stream, $125, swfVersion, tagCode);
      } else {
        var $126 = $.color = {};
        rgb($bytes, $stream, $126, swfVersion, tagCode);
      }
      if (isMorph) {
        var $127 = $.colorMorph = {};
        rgba($bytes, $stream, $127, swfVersion, tagCode);
      }
      return;
    }
    function matrix($bytes, $stream, $, swfVersion, tagCode) {
      align($bytes, $stream);
      var hasScale = readUb($bytes, $stream, 1);
      if (hasScale) {
        var bits = readUb($bytes, $stream, 5);
        $.a = readFb($bytes, $stream, bits);
        $.d = readFb($bytes, $stream, bits);
      } else {
        $.a = 1;
        $.d = 1;
      }
      var hasRotate = readUb($bytes, $stream, 1);
      if (hasRotate) {
        var bits = readUb($bytes, $stream, 5);
        $.b = readFb($bytes, $stream, bits);
        $.c = readFb($bytes, $stream, bits);
      } else {
        $.b = 0;
        $.c = 0;
      }
      var bits = readUb($bytes, $stream, 5);
      var e = readSb($bytes, $stream, bits);
      var f = readSb($bytes, $stream, bits);
      $.tx = e;
      $.ty = f;
      align($bytes, $stream);
    }
    function cxform($bytes, $stream, $, swfVersion, tagCode) {
      align($bytes, $stream);
      var hasOffsets = readUb($bytes, $stream, 1);
      var hasMultipliers = readUb($bytes, $stream, 1);
      var bits = readUb($bytes, $stream, 4);
      if (hasMultipliers) {
        $.redMultiplier = readSb($bytes, $stream, bits);
        $.greenMultiplier = readSb($bytes, $stream, bits);
        $.blueMultiplier = readSb($bytes, $stream, bits);
        if (tagCode > 4) {
          $.alphaMultiplier = readSb($bytes, $stream, bits);
        } else {
          $.alphaMultiplier = 256;
        }
      } else {
        $.redMultiplier = 256;
        $.greenMultiplier = 256;
        $.blueMultiplier = 256;
        $.alphaMultiplier = 256;
      }
      if (hasOffsets) {
        $.redOffset = readSb($bytes, $stream, bits);
        $.greenOffset = readSb($bytes, $stream, bits);
        $.blueOffset = readSb($bytes, $stream, bits);
        if (tagCode > 4) {
          $.alphaOffset = readSb($bytes, $stream, bits);
        } else {
          $.alphaOffset = 0;
        }
      } else {
        $.redOffset = 0;
        $.greenOffset = 0;
        $.blueOffset = 0;
        $.alphaOffset = 0;
      }
      align($bytes, $stream);
    }
    function fillGradient($bytes, $stream, $, swfVersion, tagCode, isMorph, type) {
      var $128 = $.matrix = {};
      matrix($bytes, $stream, $128, swfVersion, tagCode);
      if (isMorph) {
        var $129 = $.matrixMorph = {};
        matrix($bytes, $stream, $129, swfVersion, tagCode);
      }
      gradient($bytes, $stream, $, swfVersion, tagCode, isMorph, type);
    }
    function gradient($bytes, $stream, $, swfVersion, tagCode, isMorph, type) {
      if (tagCode === 83) {
        $.spreadMode = readUb($bytes, $stream, 2);
        $.interpolationMode = readUb($bytes, $stream, 2);
      } else {
        var pad = readUb($bytes, $stream, 4);
      }
      var count = $.count = readUb($bytes, $stream, 4);
      var $130 = $.records = [];
      var $131 = count;
      while ($131--) {
        var $132 = {};
        gradientRecord($bytes, $stream, $132, swfVersion, tagCode, isMorph);
        $130.push($132);
      }
      if (type === 19) {
        $.focalPoint = readFixed8($bytes, $stream);
        if (isMorph) {
          $.focalPointMorph = readFixed8($bytes, $stream);
        }
      }
    }
    function gradientRecord($bytes, $stream, $, swfVersion, tagCode, isMorph) {
      $.ratio = readUi8($bytes, $stream);
      if (tagCode > 22) {
        var $133 = $.color = {};
        rgba($bytes, $stream, $133, swfVersion, tagCode);
      } else {
        var $134 = $.color = {};
        rgb($bytes, $stream, $134, swfVersion, tagCode);
      }
      if (isMorph) {
        $.ratioMorph = readUi8($bytes, $stream);
        var $135 = $.colorMorph = {};
        rgba($bytes, $stream, $135, swfVersion, tagCode);
      }
    }
    function morphShapeWithStyle($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes) {
      var eos, bits;
      var temp = styles($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes);
      var lineBits = temp.lineBits;
      var fillBits = temp.fillBits;
      var $160 = $.records = [];
      do {
        var $161 = {};
        var temp = shapeRecord($bytes, $stream, $161, swfVersion, tagCode, isMorph, fillBits, lineBits, hasStrokes, bits);
        var eos = temp.eos;
        var flags = temp.flags;
        var type = temp.type;
        var fillBits = temp.fillBits;
        var lineBits = temp.lineBits;
        var bits = temp.bits;
        $160.push($161);
      } while (!eos);
      var temp = styleBits($bytes, $stream, $, swfVersion, tagCode);
      var fillBits = temp.fillBits;
      var lineBits = temp.lineBits;
      var $162 = $.recordsMorph = [];
      do {
        var $163 = {};
        var temp = shapeRecord($bytes, $stream, $163, swfVersion, tagCode, isMorph, fillBits, lineBits, hasStrokes, bits);
        eos = temp.eos;
        var flags = temp.flags;
        var type = temp.type;
        var fillBits = temp.fillBits;
        var lineBits = temp.lineBits;
        bits = temp.bits;
        $162.push($163);
      } while (!eos);
    }
    function shapeWithStyle($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes) {
      var eos;
      var temp = styles($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes);
      var fillBits = temp.fillBits;
      var lineBits = temp.lineBits;
      var $160 = $.records = [];
      do {
        var $161 = {};
        var temp = shapeRecord($bytes, $stream, $161, swfVersion, tagCode, isMorph, fillBits, lineBits, hasStrokes, bits);
        eos = temp.eos;
        var flags = temp.flags;
        var type = temp.type;
        var fillBits = temp.fillBits;
        var lineBits = temp.lineBits;
        var bits = temp.bits;
        $160.push($161);
      } while (!eos);
    }
    function shapeRecord($bytes, $stream, $, swfVersion, tagCode, isMorph, fillBits, lineBits, hasStrokes, bits) {
      var type = $.type = readUb($bytes, $stream, 1);
      var flags = readUb($bytes, $stream, 5);
      var eos = $.eos = !(type || flags);
      if (type) {
        var temp = shapeRecordEdge($bytes, $stream, $, swfVersion, tagCode, flags, bits);
        var bits = temp.bits;
      } else {
        var temp = shapeRecordSetup($bytes, $stream, $, swfVersion, tagCode, flags, isMorph, fillBits, lineBits, hasStrokes, bits);
        var fillBits = temp.fillBits;
        var lineBits = temp.lineBits;
        var bits = temp.bits;
      }
      return {
        type: type,
        flags: flags,
        eos: eos,
        fillBits: fillBits,
        lineBits: lineBits,
        bits: bits
      };
    }
    function shapeRecordEdge($bytes, $stream, $, swfVersion, tagCode, flags, bits) {
      var isStraight = 0, tmp = 0, bits = 0, isGeneral = 0, isVertical = 0;
      isStraight = $.isStraight = flags >> 4;
      tmp = flags & 15;
      bits = tmp + 2;
      if (isStraight) {
        isGeneral = $.isGeneral = readUb($bytes, $stream, 1);
        if (isGeneral) {
          $.deltaX = readSb($bytes, $stream, bits);
          $.deltaY = readSb($bytes, $stream, bits);
        } else {
          isVertical = $.isVertical = readUb($bytes, $stream, 1);
          if (isVertical) {
            $.deltaY = readSb($bytes, $stream, bits);
          } else {
            $.deltaX = readSb($bytes, $stream, bits);
          }
        }
      } else {
        $.controlDeltaX = readSb($bytes, $stream, bits);
        $.controlDeltaY = readSb($bytes, $stream, bits);
        $.anchorDeltaX = readSb($bytes, $stream, bits);
        $.anchorDeltaY = readSb($bytes, $stream, bits);
      }
      return {
        bits: bits
      };
    }
    function shapeRecordSetup($bytes, $stream, $, swfVersion, tagCode, flags, isMorph, fillBits, lineBits, hasStrokes, bits) {
      var hasNewStyles = 0, hasLineStyle = 0, hasFillStyle1 = 0;
      var hasFillStyle0 = 0, move = 0;
      if (tagCode > 2) {
        hasNewStyles = $.hasNewStyles = flags >> 4;
      } else {
        hasNewStyles = $.hasNewStyles = 0;
      }
      hasLineStyle = $.hasLineStyle = flags >> 3 & 1;
      hasFillStyle1 = $.hasFillStyle1 = flags >> 2 & 1;
      hasFillStyle0 = $.hasFillStyle0 = flags >> 1 & 1;
      move = $.move = flags & 1;
      if (move) {
        bits = readUb($bytes, $stream, 5);
        $.moveX = readSb($bytes, $stream, bits);
        $.moveY = readSb($bytes, $stream, bits);
      }
      if (hasFillStyle0) {
        $.fillStyle0 = readUb($bytes, $stream, fillBits);
      }
      if (hasFillStyle1) {
        $.fillStyle1 = readUb($bytes, $stream, fillBits);
      }
      if (hasLineStyle) {
        $.lineStyle = readUb($bytes, $stream, lineBits);
      }
      if (hasNewStyles) {
        var temp = styles($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes);
        var lineBits = temp.lineBits;
        var fillBits = temp.fillBits;
      }
      return {
        lineBits: lineBits,
        fillBits: fillBits,
        bits: bits
      };
    }
    function styles($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes) {
      fillStyleArray($bytes, $stream, $, swfVersion, tagCode, isMorph);
      lineStyleArray($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes);
      var temp = styleBits($bytes, $stream, $, swfVersion, tagCode);
      var fillBits = temp.fillBits;
      var lineBits = temp.lineBits;
      return {
        fillBits: fillBits,
        lineBits: lineBits
      };
    }
    function fillStyleArray($bytes, $stream, $, swfVersion, tagCode, isMorph) {
      var count;
      var tmp = readUi8($bytes, $stream);
      if (tagCode > 2 && tmp === 255) {
        count = readUi16($bytes, $stream);
      } else {
        count = tmp;
      }
      var $4 = $.fillStyles = [];
      var $5 = count;
      while ($5--) {
        var $6 = {};
        fillStyle($bytes, $stream, $6, swfVersion, tagCode, isMorph);
        $4.push($6);
      }
    }
    function lineStyleArray($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes) {
      var count;
      var tmp = readUi8($bytes, $stream);
      if (tagCode > 2 && tmp === 255) {
        count = readUi16($bytes, $stream);
      } else {
        count = tmp;
      }
      var $138 = $.lineStyles = [];
      var $139 = count;
      while ($139--) {
        var $140 = {};
        lineStyle($bytes, $stream, $140, swfVersion, tagCode, isMorph, hasStrokes);
        $138.push($140);
      }
    }
    function styleBits($bytes, $stream, $, swfVersion, tagCode) {
      align($bytes, $stream);
      var fillBits = readUb($bytes, $stream, 4);
      var lineBits = readUb($bytes, $stream, 4);
      return {
        fillBits: fillBits,
        lineBits: lineBits
      };
    }
    function fillStyle($bytes, $stream, $, swfVersion, tagCode, isMorph) {
      var type = $.type = readUi8($bytes, $stream);
      switch (type) {
      case 0:
        fillSolid($bytes, $stream, $, swfVersion, tagCode, isMorph);
        break;
      case 16:
      case 18:
      case 19:
        fillGradient($bytes, $stream, $, swfVersion, tagCode, isMorph, type);
        break;
      case 64:
      case 65:
      case 66:
      case 67:
        fillBitmap($bytes, $stream, $, swfVersion, tagCode, isMorph, type);
        break;
      default:
      }
    }
    function lineStyle($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes) {
      $.width = readUi16($bytes, $stream);
      if (isMorph) {
        $.widthMorph = readUi16($bytes, $stream);
      }
      if (hasStrokes) {
        align($bytes, $stream);
        $.startCapStyle = readUb($bytes, $stream, 2);
        var joinStyle = $.joinStyle = readUb($bytes, $stream, 2);
        var hasFill = $.hasFill = readUb($bytes, $stream, 1);
        $.noHscale = readUb($bytes, $stream, 1);
        $.noVscale = readUb($bytes, $stream, 1);
        $.pixelHinting = readUb($bytes, $stream, 1);
        var reserved = readUb($bytes, $stream, 5);
        $.noClose = readUb($bytes, $stream, 1);
        $.endCapStyle = readUb($bytes, $stream, 2);
        if (joinStyle === 2) {
          $.miterLimitFactor = readFixed8($bytes, $stream);
        }
        if (hasFill) {
          var $141 = $.fillStyle = {};
          fillStyle($bytes, $stream, $141, swfVersion, tagCode, isMorph);
        } else {
          var $155 = $.color = {};
          rgba($bytes, $stream, $155, swfVersion, tagCode);
          if (isMorph) {
            var $156 = $.colorMorph = {};
            rgba($bytes, $stream, $156, swfVersion, tagCode);
          }
        }
      } else {
        if (tagCode > 22) {
          var $157 = $.color = {};
          rgba($bytes, $stream, $157, swfVersion, tagCode);
        } else {
          var $158 = $.color = {};
          rgb($bytes, $stream, $158, swfVersion, tagCode);
        }
        if (isMorph) {
          var $159 = $.colorMorph = {};
          rgba($bytes, $stream, $159, swfVersion, tagCode);
        }
      }
    }
    function fillBitmap($bytes, $stream, $, swfVersion, tagCode, isMorph, type) {
      $.bitmapId = readUi16($bytes, $stream);
      var $18 = $.matrix = {};
      matrix($bytes, $stream, $18, swfVersion, tagCode);
      if (isMorph) {
        var $19 = $.matrixMorph = {};
        matrix($bytes, $stream, $19, swfVersion, tagCode);
      }
      $.condition = type === 64 || type === 67;
    }
    function filterGlow($bytes, $stream, $, swfVersion, tagCode, type) {
      var count;
      if (type === 4 || type === 7) {
        count = readUi8($bytes, $stream);
      } else {
        count = 1;
      }
      var $5 = $.colors = [];
      var $6 = count;
      while ($6--) {
        var $7 = {};
        rgba($bytes, $stream, $7, swfVersion, tagCode);
        $5.push($7);
      }
      if (type === 3) {
        var $8 = $.higlightColor = {};
        rgba($bytes, $stream, $8, swfVersion, tagCode);
      }
      if (type === 4 || type === 7) {
        var $9 = $.ratios = [];
        var $10 = count;
        while ($10--) {
          $9.push(readUi8($bytes, $stream));
        }
      }
      $.blurX = readFixed($bytes, $stream);
      $.blurY = readFixed($bytes, $stream);
      if (type !== 2) {
        $.angle = readFixed($bytes, $stream);
        $.distance = readFixed($bytes, $stream);
      }
      $.strength = readFixed8($bytes, $stream);
      $.innerShadow = readUb($bytes, $stream, 1);
      $.knockout = readUb($bytes, $stream, 1);
      $.compositeSource = readUb($bytes, $stream, 1);
      if (type === 3) {
        $.onTop = readUb($bytes, $stream, 1);
      } else {
        var reserved = readUb($bytes, $stream, 1);
      }
      if (type === 4 || type === 7) {
        $.passes = readUb($bytes, $stream, 4);
      } else {
        var reserved = readUb($bytes, $stream, 4);
      }
    }
    function filterBlur($bytes, $stream, $, swfVersion, tagCode) {
      $.blurX = readFixed($bytes, $stream);
      $.blurY = readFixed($bytes, $stream);
      $.passes = readUb($bytes, $stream, 5);
      var reserved = readUb($bytes, $stream, 3);
    }
    function filterConvolution($bytes, $stream, $, swfVersion, tagCode) {
      var columns = $.columns = readUi8($bytes, $stream);
      var rows = $.rows = readUi8($bytes, $stream);
      $.divisor = readFloat($bytes, $stream);
      $.bias = readFloat($bytes, $stream);
      var $17 = $.weights = [];
      var $18 = columns * rows;
      while ($18--) {
        $17.push(readFloat($bytes, $stream));
      }
      var $19 = $.defaultColor = {};
      rgba($bytes, $stream, $19, swfVersion, tagCode);
      var reserved = readUb($bytes, $stream, 6);
      $.clamp = readUb($bytes, $stream, 1);
      $.preserveAlpha = readUb($bytes, $stream, 1);
    }
    function filterColorMatrix($bytes, $stream, $, swfVersion, tagCode) {
      var $20 = $.matrix = [];
      var $21 = 20;
      while ($21--) {
        $20.push(readFloat($bytes, $stream));
      }
    }
    function anyFilter($bytes, $stream, $, swfVersion, tagCode) {
      var type = $.type = readUi8($bytes, $stream);
      switch (type) {
      case 0:
      case 2:
      case 3:
      case 4:
      case 7:
        filterGlow($bytes, $stream, $, swfVersion, tagCode, type);
        break;
      case 1:
        filterBlur($bytes, $stream, $, swfVersion, tagCode);
        break;
      case 5:
        filterConvolution($bytes, $stream, $, swfVersion, tagCode);
        break;
      case 6:
        filterColorMatrix($bytes, $stream, $, swfVersion, tagCode);
        break;
      default:
      }
    }
    function events($bytes, $stream, $, swfVersion, tagCode) {
      var flags, keyPress;
      if (swfVersion >= 6) {
        flags = readUi32($bytes, $stream);
      } else {
        flags = readUi16($bytes, $stream);
      }
      var eoe = $.eoe = !flags;
      $.onKeyUp = flags >> 7 & 1;
      $.onKeyDown = flags >> 6 & 1;
      $.onMouseUp = flags >> 5 & 1;
      $.onMouseDown = flags >> 4 & 1;
      $.onMouseMove = flags >> 3 & 1;
      $.onUnload = flags >> 2 & 1;
      $.onEnterFrame = flags >> 1 & 1;
      $.onLoad = flags & 1;
      if (swfVersion >= 6) {
        $.onDragOver = flags >> 15 & 1;
        $.onRollOut = flags >> 14 & 1;
        $.onRollOver = flags >> 13 & 1;
        $.onReleaseOutside = flags >> 12 & 1;
        $.onRelease = flags >> 11 & 1;
        $.onPress = flags >> 10 & 1;
        $.onInitialize = flags >> 9 & 1;
        $.onData = flags >> 8 & 1;
        if (swfVersion >= 7) {
          $.onConstruct = flags >> 18 & 1;
        } else {
          $.onConstruct = 0;
        }
        keyPress = $.keyPress = flags >> 17 & 1;
        $.onDragOut = flags >> 16 & 1;
      }
      if (!eoe) {
        var length = $.length = readUi32($bytes, $stream);
        if (keyPress) {
          $.keyCode = readUi8($bytes, $stream);
        }
        $.actionsData = readBinary($bytes, $stream, length - (keyPress ? 1 : 0));
      }
      return {
        eoe: eoe
      };
    }
    function kerning($bytes, $stream, $, swfVersion, tagCode, wide) {
      if (wide) {
        $.code1 = readUi16($bytes, $stream);
        $.code2 = readUi16($bytes, $stream);
      } else {
        $.code1 = readUi8($bytes, $stream);
        $.code2 = readUi8($bytes, $stream);
      }
      $.adjustment = readUi16($bytes, $stream);
    }
    function textEntry($bytes, $stream, $, swfVersion, tagCode, glyphBits, advanceBits) {
      $.glyphIndex = readUb($bytes, $stream, glyphBits);
      $.advance = readSb($bytes, $stream, advanceBits);
    }
    function textRecordSetup($bytes, $stream, $, swfVersion, tagCode, flags) {
      var hasFont = $.hasFont = flags >> 3 & 1;
      var hasColor = $.hasColor = flags >> 2 & 1;
      var hasMoveY = $.hasMoveY = flags >> 1 & 1;
      var hasMoveX = $.hasMoveX = flags & 1;
      if (hasFont) {
        $.fontId = readUi16($bytes, $stream);
      }
      if (hasColor) {
        if (tagCode === 33) {
          var $4 = $.color = {};
          rgba($bytes, $stream, $4, swfVersion, tagCode);
        } else {
          var $5 = $.color = {};
          rgb($bytes, $stream, $5, swfVersion, tagCode);
        }
      }
      if (hasMoveX) {
        $.moveX = readSi16($bytes, $stream);
      }
      if (hasMoveY) {
        $.moveY = readSi16($bytes, $stream);
      }
      if (hasFont) {
        $.fontHeight = readUi16($bytes, $stream);
      }
    }
    function textRecord($bytes, $stream, $, swfVersion, tagCode, glyphBits, advanceBits) {
      var glyphCount;
      align($bytes, $stream);
      var flags = readUb($bytes, $stream, 8);
      var eot = $.eot = !flags;
      textRecordSetup($bytes, $stream, $, swfVersion, tagCode, flags);
      if (!eot) {
        var tmp = readUi8($bytes, $stream);
        if (swfVersion > 6) {
          glyphCount = $.glyphCount = tmp;
        } else {
          glyphCount = $.glyphCount = tmp & 127;
        }
        var $6 = $.entries = [];
        var $7 = glyphCount;
        while ($7--) {
          var $8 = {};
          textEntry($bytes, $stream, $8, swfVersion, tagCode, glyphBits, advanceBits);
          $6.push($8);
        }
      }
      return {
        eot: eot
      };
    }
    function soundEnvelope($bytes, $stream, $, swfVersion, tagCode) {
      $.pos44 = readUi32($bytes, $stream);
      $.volumeLeft = readUi16($bytes, $stream);
      $.volumeRight = readUi16($bytes, $stream);
    }
    function soundInfo($bytes, $stream, $, swfVersion, tagCode) {
      var reserved = readUb($bytes, $stream, 2);
      $.stop = readUb($bytes, $stream, 1);
      $.noMultiple = readUb($bytes, $stream, 1);
      var hasEnvelope = $.hasEnvelope = readUb($bytes, $stream, 1);
      var hasLoops = $.hasLoops = readUb($bytes, $stream, 1);
      var hasOutPoint = $.hasOutPoint = readUb($bytes, $stream, 1);
      var hasInPoint = $.hasInPoint = readUb($bytes, $stream, 1);
      if (hasInPoint) {
        $.inPoint = readUi32($bytes, $stream);
      }
      if (hasOutPoint) {
        $.outPoint = readUi32($bytes, $stream);
      }
      if (hasLoops) {
        $.loopCount = readUi16($bytes, $stream);
      }
      if (hasEnvelope) {
        var envelopeCount = $.envelopeCount = readUi8($bytes, $stream);
        var $1 = $.envelopes = [];
        var $2 = envelopeCount;
        while ($2--) {
          var $3 = {};
          soundEnvelope($bytes, $stream, $3, swfVersion, tagCode);
          $1.push($3);
        }
      }
    }
    function button($bytes, $stream, $, swfVersion, tagCode) {
      var hasFilters, blend;
      var flags = readUi8($bytes, $stream);
      var eob = $.eob = !flags;
      if (swfVersion >= 8) {
        blend = $.blend = flags >> 5 & 1;
        hasFilters = $.hasFilters = flags >> 4 & 1;
      } else {
        blend = $.blend = 0;
        hasFilters = $.hasFilters = 0;
      }
      $.stateHitTest = flags >> 3 & 1;
      $.stateDown = flags >> 2 & 1;
      $.stateOver = flags >> 1 & 1;
      $.stateUp = flags & 1;
      if (!eob) {
        $.symbolId = readUi16($bytes, $stream);
        $.depth = readUi16($bytes, $stream);
        var $2 = $.matrix = {};
        matrix($bytes, $stream, $2, swfVersion, tagCode);
        if (tagCode === 34) {
          var $3 = $.cxform = {};
          cxform($bytes, $stream, $3, swfVersion, tagCode);
        }
        if (hasFilters) {
          $.filterCount = readUi8($bytes, $stream);
          var $4 = $.filters = {};
          anyFilter($bytes, $stream, $4, swfVersion, tagCode);
        }
        if (blend) {
          $.blendMode = readUi8($bytes, $stream);
        }
      }
      return {
        eob: eob
      };
    }
    function buttonCondAction($bytes, $stream, $, swfVersion, tagCode) {
      var buttonCondSize = readUi16($bytes, $stream);
      var buttonConditions = readUi16($bytes, $stream);
      $.idleToOverDown = buttonConditions >> 7 & 1;
      $.outDownToIdle = buttonConditions >> 6 & 1;
      $.outDownToOverDown = buttonConditions >> 5 & 1;
      $.overDownToOutDown = buttonConditions >> 4 & 1;
      $.overDownToOverUp = buttonConditions >> 3 & 1;
      $.overUpToOverDown = buttonConditions >> 2 & 1;
      $.overUpToIdle = buttonConditions >> 1 & 1;
      $.idleToOverUp = buttonConditions & 1;
      $.mouseEventFlags = buttonConditions & 511;
      $.keyPress = buttonConditions >> 9 & 127;
      $.overDownToIdle = buttonConditions >> 8 & 1;
      if (!buttonCondSize) {
        $.actionsData = readBinary($bytes, $stream, 0);
      } else {
        $.actionsData = readBinary($bytes, $stream, buttonCondSize - 4);
      }
    }
    function shape($bytes, $stream, $, swfVersion, tagCode) {
      var eos;
      var temp = styleBits($bytes, $stream, $, swfVersion, tagCode);
      var fillBits = temp.fillBits;
      var lineBits = temp.lineBits;
      var $4 = $.records = [];
      do {
        var $5 = {};
        var isMorph = false;
        var hasStrokes = false;
        var temp = shapeRecord($bytes, $stream, $5, swfVersion, tagCode, isMorph, fillBits, lineBits, hasStrokes, bits);
        eos = temp.eos;
        var fillBits = temp.fillBits;
        var lineBits = temp.lineBits;
        var bits = bits;
        $4.push($5);
      } while (!eos);
    }
    return {
      0: undefined,
      1: undefined,
      2: defineShape,
      4: placeObject,
      5: removeObject,
      6: defineImage,
      7: defineButton,
      8: defineJPEGTables,
      9: setBackgroundColor,
      10: defineFont,
      11: defineLabel,
      12: doAction,
      13: undefined,
      14: defineSound,
      15: startSound,
      17: undefined,
      18: soundStreamHead,
      19: soundStreamBlock,
      20: defineBitmap,
      21: defineImage,
      22: defineShape,
      23: undefined,
      24: undefined,
      26: placeObject,
      28: removeObject,
      32: defineShape,
      33: defineLabel,
      34: defineButton,
      35: defineImage,
      36: defineBitmap,
      37: defineText,
      39: undefined,
      43: frameLabel,
      45: soundStreamHead,
      46: defineShape,
      48: defineFont2,
      56: exportAssets,
      57: undefined,
      58: undefined,
      59: doAction,
      60: undefined,
      61: undefined,
      62: undefined,
      64: undefined,
      65: undefined,
      66: undefined,
      69: fileAttributes,
      70: placeObject,
      71: undefined,
      72: doABC,
      73: undefined,
      74: undefined,
      75: defineFont2,
      76: symbolClass,
      77: undefined,
      78: defineScalingGrid,
      82: doABC,
      83: defineShape,
      84: defineShape,
      86: defineScene,
      87: defineBinaryData,
      88: undefined,
      89: startSound,
      90: defineImage,
      91: undefined
    };
  }(this);
var readHeader = function readHeader($bytes, $stream, $, swfVersion, tagCode) {
  $ || ($ = {});
  var $0 = $.bbox = {};
  align($bytes, $stream);
  var bits = readUb($bytes, $stream, 5);
  var xMin = readSb($bytes, $stream, bits);
  var xMax = readSb($bytes, $stream, bits);
  var yMin = readSb($bytes, $stream, bits);
  var yMax = readSb($bytes, $stream, bits);
  $0.xMin = xMin;
  $0.xMax = xMax;
  $0.yMin = yMin;
  $0.yMax = yMax;
  align($bytes, $stream);
  var frameRateFraction = readUi8($bytes, $stream);
  $.frameRate = readUi8($bytes, $stream) + frameRateFraction / 256;
  $.frameCount = readUi16($bytes, $stream);
  return $;
};
function readTags(context, stream, swfVersion, final, onprogress, onexception) {
  var tags = context.tags;
  var bytes = stream.bytes;
  var lastSuccessfulPosition;
  var tag = null;
  if (context._readTag) {
    tag = context._readTag;
    context._readTag = null;
  }
  try {
    while (stream.pos < stream.end) {
      lastSuccessfulPosition = stream.pos;
      stream.ensure(2);
      var tagCodeAndLength = readUi16(bytes, stream);
      if (!tagCodeAndLength) {
        final = true;
        break;
      }
      var tagCode = tagCodeAndLength >> 6;
      var length = tagCodeAndLength & 63;
      if (length === 63) {
        stream.ensure(4);
        length = readUi32(bytes, stream);
      }
      if (tag) {
        if (tagCode === 1 && tag.code === 1) {
          tag.repeat++;
          stream.pos += length;
          continue;
        }
        tags.push(tag);
        if (onprogress && tag.id !== undefined) {
          onprogress(context);
        }
        tag = null;
      }
      stream.ensure(length);
      var substream = stream.substream(stream.pos, stream.pos += length);
      var subbytes = substream.bytes;
      var nextTag = {
          code: tagCode
        };
      if (tagCode === 39) {
        nextTag.type = 'sprite';
        nextTag.id = readUi16(subbytes, substream);
        nextTag.frameCount = readUi16(subbytes, substream);
        nextTag.tags = [];
        readTags(nextTag, substream, swfVersion, true);
      } else if (tagCode === 1) {
        nextTag.repeat = 1;
      } else {
        var handler = tagHandler[tagCode];
        if (handler) {
          handler(subbytes, substream, nextTag, swfVersion, tagCode);
        }
      }
      tag = nextTag;
    }
    if (tag && final) {
      tag.finalTag = true;
      tags.push(tag);
      if (onprogress) {
        onprogress(context);
      }
    } else {
      context._readTag = tag;
    }
  } catch (e) {
    if (e !== StreamNoDataError) {
      onexception && onexception(e);
      throw e;
    }
    stream.pos = lastSuccessfulPosition;
    context._readTag = tag;
  }
}
function HeadTailBuffer(defaultSize) {
  this.bufferSize = defaultSize || 16;
  this.buffer = new Uint8Array(this.bufferSize);
  this.pos = 0;
}
HeadTailBuffer.prototype = {
  push: function (data, need) {
    var bufferLengthNeed = this.pos + data.length;
    if (this.bufferSize < bufferLengthNeed) {
      var newBufferSize = this.bufferSize;
      while (newBufferSize < bufferLengthNeed) {
        newBufferSize <<= 1;
      }
      var newBuffer = new Uint8Array(newBufferSize);
      if (this.bufferSize > 0) {
        newBuffer.set(this.buffer);
      }
      this.buffer = newBuffer;
      this.bufferSize = newBufferSize;
    }
    this.buffer.set(data, this.pos);
    this.pos += data.length;
    if (need)
      return this.pos >= need;
  },
  getHead: function (size) {
    return this.buffer.subarray(0, size);
  },
  getTail: function (offset) {
    return this.buffer.subarray(offset, this.pos);
  },
  removeHead: function (size) {
    var tail = this.getTail(size);
    this.buffer = new Uint8Array(this.bufferSize);
    this.buffer.set(tail);
    this.pos = tail.length;
  },
  get arrayBuffer() {
    return this.buffer.buffer;
  },
  get length() {
    return this.pos;
  },
  createStream: function () {
    return new Stream(this.arrayBuffer, 0, this.length);
  }
};
function CompressedPipe(target, length) {
  this.target = target;
  this.length = length;
  this.initialize = true;
  this.buffer = new HeadTailBuffer(8096);
  this.state = {
    bitBuffer: 0,
    bitLength: 0,
    compression: {
      header: null,
      distanceTable: null,
      literalTable: null,
      sym: null,
      len: null,
      sym2: null
    }
  };
  this.output = {
    data: new Uint8Array(length),
    available: 0,
    completed: false
  };
}
CompressedPipe.prototype = {
  push: function (data, progressInfo) {
    var buffer = this.buffer;
    if (this.initialize) {
      if (!buffer.push(data, 2))
        return;
      var headerBytes = buffer.getHead(2);
      verifyDeflateHeader(headerBytes);
      buffer.removeHead(2);
      this.initialize = false;
    } else {
      buffer.push(data);
    }
    var stream = buffer.createStream();
    stream.bitBuffer = this.state.bitBuffer;
    stream.bitLength = this.state.bitLength;
    var output = this.output;
    var lastAvailable = output.available;
    try {
      do {
        inflateBlock(stream, output, this.state.compression);
      } while (stream.pos < buffer.length && !output.completed);
    } catch (e) {
      if (e !== InflateNoDataError)
        throw e;
    } finally {
      this.state.bitBuffer = stream.bitBuffer;
      this.state.bitLength = stream.bitLength;
    }
    buffer.removeHead(stream.pos);
    this.target.push(output.data.subarray(lastAvailable, output.available), progressInfo);
  }
};
function BodyParser(swfVersion, length, options) {
  this.swf = {
    swfVersion: swfVersion,
    parseTime: 0
  };
  this.buffer = new HeadTailBuffer(32768);
  this.initialize = true;
  this.totalRead = 0;
  this.length = length;
  this.options = options;
}
BodyParser.prototype = {
  push: function (data, progressInfo) {
    if (data.length === 0)
      return;
    var swf = this.swf;
    var swfVersion = swf.swfVersion;
    var buffer = this.buffer;
    var options = this.options;
    var stream;
    if (this.initialize) {
      var PREFETCH_SIZE = 27;
      if (!buffer.push(data, PREFETCH_SIZE))
        return;
      stream = buffer.createStream();
      var bytes = stream.bytes;
      readHeader(bytes, stream, swf);
      var nextTagHeader = readUi16(bytes, stream);
      var FILE_ATTRIBUTES_LENGTH = 4;
      if (nextTagHeader == (SWF_TAG_CODE_FILE_ATTRIBUTES << 6 | FILE_ATTRIBUTES_LENGTH)) {
        stream.ensure(FILE_ATTRIBUTES_LENGTH);
        var substream = stream.substream(stream.pos, stream.pos += FILE_ATTRIBUTES_LENGTH);
        var handler = tagHandler[SWF_TAG_CODE_FILE_ATTRIBUTES];
        var fileAttributesTag = {
            code: SWF_TAG_CODE_FILE_ATTRIBUTES
          };
        handler(substream.bytes, substream, fileAttributesTag, swfVersion, SWF_TAG_CODE_FILE_ATTRIBUTES);
        swf.fileAttributes = fileAttributesTag;
      } else {
        stream.pos -= 2;
        swf.fileAttributes = {};
      }
      if (options.onstart)
        options.onstart(swf);
      swf.tags = [];
      this.initialize = false;
    } else {
      buffer.push(data);
      stream = buffer.createStream();
    }
    var finalBlock = false;
    if (progressInfo) {
      swf.bytesLoaded = progressInfo.bytesLoaded;
      swf.bytesTotal = progressInfo.bytesTotal;
      finalBlock = progressInfo.bytesLoaded >= progressInfo.bytesTotal;
    }
    var readStartTime = performance.now();
    readTags(swf, stream, swfVersion, finalBlock, options.onprogress, options.onexception);
    swf.parseTime += performance.now() - readStartTime;
    var read = stream.pos;
    buffer.removeHead(read);
    this.totalRead += read;
    if (options.oncomplete && swf.tags[swf.tags.length - 1].finalTag) {
      options.oncomplete(swf);
    }
  }
};
SWF.parseAsync = function swf_parseAsync(options) {
  var buffer = new HeadTailBuffer();
  var pipe = {
      push: function (data, progressInfo) {
        if (this.target !== undefined) {
          return this.target.push(data, progressInfo);
        }
        if (!buffer.push(data, 8)) {
          return null;
        }
        var bytes = buffer.getHead(8);
        var magic1 = bytes[0];
        var magic2 = bytes[1];
        var magic3 = bytes[2];
        if ((magic1 === 70 || magic1 === 67) && magic2 === 87 && magic3 === 83) {
          var swfVersion = bytes[3];
          var compressed = magic1 === 67;
          parseSWF(compressed, swfVersion, progressInfo);
          buffer = null;
          return;
        }
        var isImage = false;
        var imageType;
        if (magic1 === 255 && magic2 === 216 && magic3 === 255) {
          isImage = true;
          imageType = 'image/jpeg';
        } else if (magic1 === 137 && magic2 === 80 && magic3 === 78) {
          isImage = true;
          imageType = 'image/png';
        }
        if (isImage) {
          parseImage(data, progressInfo.bytesTotal, imageType);
        }
        buffer = null;
      },
      close: function () {
        if (buffer) {
          var symbol = {
              command: 'empty',
              data: buffer.buffer.subarray(0, buffer.pos)
            };
          options.oncomplete && options.oncomplete(symbol);
        }
        if (this.target !== undefined && this.target.close) {
          this.target.close();
        }
      }
    };
  function parseSWF(compressed, swfVersion, progressInfo) {
    var stream = buffer.createStream();
    stream.pos += 4;
    var fileLength = readUi32(null, stream);
    var bodyLength = fileLength - 8;
    var target = new BodyParser(swfVersion, bodyLength, options);
    if (compressed) {
      target = new CompressedPipe(target, bodyLength);
    }
    target.push(buffer.getTail(8), progressInfo);
    pipe['target'] = target;
  }
  function parseImage(data, bytesTotal, type) {
    var buffer = new Uint8Array(bytesTotal);
    buffer.set(data);
    var bufferPos = data.length;
    pipe['target'] = {
      push: function (data) {
        buffer.set(data, bufferPos);
        bufferPos += data.length;
      },
      close: function () {
        var props = {};
        var chunks;
        if (type == 'image/jpeg') {
          chunks = parseJpegChunks(props, buffer);
        } else {
          chunks = [
            buffer
          ];
        }
        var symbol = {
            type: 'image',
            props: props,
            data: new Blob(chunks, {
              type: type
            })
          };
        options.oncomplete && options.oncomplete(symbol);
      }
    };
  }
  return pipe;
};
SWF.parse = function (buffer, options) {
  if (!options)
    options = {};
  var pipe = SWF.parseAsync(options);
  var bytes = new Uint8Array(buffer);
  var progressInfo = {
      bytesLoaded: bytes.length,
      bytesTotal: bytes.length
    };
  pipe.push(bytes, progressInfo);
  pipe.close();
};
var $RELEASE = false;
var isWorker = typeof window === 'undefined';
if (isWorker && !true) {
  importScripts.apply(null, [
    '../../lib/DataView.js/DataView.js',
    '../flash/util.js',
    'config.js',
    'swf.js',
    'types.js',
    'structs.js',
    'tags.js',
    'inflate.js',
    'stream.js',
    'templates.js',
    'generator.js',
    'handlers.js',
    'parser.js',
    'bitmap.js',
    'button.js',
    'font.js',
    'image.js',
    'label.js',
    'shape.js',
    'sound.js',
    'text.js'
  ]);
}
function defineSymbol(swfTag, symbols) {
  var symbol;
  switch (swfTag.code) {
  case SWF_TAG_CODE_DEFINE_BITS:
  case SWF_TAG_CODE_DEFINE_BITS_JPEG2:
  case SWF_TAG_CODE_DEFINE_BITS_JPEG3:
  case SWF_TAG_CODE_DEFINE_BITS_JPEG4:
  case SWF_TAG_CODE_JPEG_TABLES:
    symbol = defineImage(swfTag, symbols);
    break;
  case SWF_TAG_CODE_DEFINE_BITS_LOSSLESS:
  case SWF_TAG_CODE_DEFINE_BITS_LOSSLESS2:
    symbol = defineBitmap(swfTag);
    break;
  case SWF_TAG_CODE_DEFINE_BUTTON:
  case SWF_TAG_CODE_DEFINE_BUTTON2:
    symbol = defineButton(swfTag, symbols);
    break;
  case SWF_TAG_CODE_DEFINE_EDIT_TEXT:
    symbol = defineText(swfTag, symbols);
    break;
  case SWF_TAG_CODE_DEFINE_FONT:
  case SWF_TAG_CODE_DEFINE_FONT2:
  case SWF_TAG_CODE_DEFINE_FONT3:
  case SWF_TAG_CODE_DEFINE_FONT4:
    symbol = defineFont(swfTag, symbols);
    break;
  case SWF_TAG_CODE_DEFINE_MORPH_SHAPE:
  case SWF_TAG_CODE_DEFINE_MORPH_SHAPE2:
  case SWF_TAG_CODE_DEFINE_SHAPE:
  case SWF_TAG_CODE_DEFINE_SHAPE2:
  case SWF_TAG_CODE_DEFINE_SHAPE3:
  case SWF_TAG_CODE_DEFINE_SHAPE4:
    symbol = defineShape(swfTag, symbols);
    break;
  case SWF_TAG_CODE_DEFINE_SOUND:
    symbol = defineSound(swfTag, symbols);
    break;
  case SWF_TAG_CODE_DEFINE_BINARY_DATA:
    symbol = {
      type: 'binary',
      id: swfTag.id,
      data: swfTag.data
    };
    break;
  case SWF_TAG_CODE_DEFINE_SPRITE:
    var depths = {};
    var frame = {
        type: 'frame'
      };
    var frames = [];
    var tags = swfTag.tags;
    var frameScripts = null;
    var frameIndex = 0;
    var soundStream = null;
    for (var i = 0, n = tags.length; i < n; i++) {
      var tag = tags[i];
      switch (tag.code) {
      case SWF_TAG_CODE_DO_ACTION:
        if (!frameScripts)
          frameScripts = [];
        frameScripts.push(frameIndex);
        frameScripts.push(tag.actionsData);
        break;
      case SWF_TAG_CODE_START_SOUND:
        var startSounds = frame.startSounds || (frame.startSounds = []);
        startSounds.push(tag);
        break;
      case SWF_TAG_CODE_SOUND_STREAM_HEAD:
        try {
          soundStream = createSoundStream(tag);
          frame.soundStream = soundStream.info;
        } catch (e) {
        }
        break;
      case SWF_TAG_CODE_SOUND_STREAM_BLOCK:
        if (soundStream) {
          frame.soundStreamBlock = soundStream.decode(tag.data);
        }
        break;
      case SWF_TAG_CODE_FRAME_LABEL:
        frame.labelName = tag.name;
        break;
      case SWF_TAG_CODE_PLACE_OBJECT:
      case SWF_TAG_CODE_PLACE_OBJECT2:
      case SWF_TAG_CODE_PLACE_OBJECT3:
        depths[tag.depth] = tag;
        break;
      case SWF_TAG_CODE_REMOVE_OBJECT:
      case SWF_TAG_CODE_REMOVE_OBJECT2:
        depths[tag.depth] = null;
        break;
      case SWF_TAG_CODE_SHOW_FRAME:
        frameIndex += tag.repeat;
        frame.repeat = tag.repeat;
        frame.depths = depths;
        frames.push(frame);
        depths = {};
        frame = {
          type: 'frame'
        };
        break;
      }
    }
    symbol = {
      type: 'sprite',
      id: swfTag.id,
      frameCount: swfTag.frameCount,
      frames: frames,
      frameScripts: frameScripts
    };
    break;
  case SWF_TAG_CODE_DEFINE_TEXT:
  case SWF_TAG_CODE_DEFINE_TEXT2:
    symbol = defineLabel(swfTag, symbols);
    break;
  }
  if (!symbol) {
    return {
      command: 'error',
      message: 'unknown symbol type: ' + swfTag.code
    };
  }
  symbol.isSymbol = true;
  symbols[swfTag.id] = symbol;
  return symbol;
}
function createParsingContext(commitData) {
  var depths = {};
  var symbols = {};
  var frame = {
      type: 'frame'
    };
  var tagsProcessed = 0;
  var soundStream = null;
  var lastProgressSent = 0;
  return {
    onstart: function (result) {
      commitData({
        command: 'init',
        result: result
      });
    },
    onprogress: function (result) {
      if (Date.now() - lastProgressSent > 1000 / 24 || result.bytesLoaded === result.bytesTotal) {
        commitData({
          command: 'progress',
          result: {
            bytesLoaded: result.bytesLoaded,
            bytesTotal: result.bytesTotal
          }
        });
        lastProgressSent = Date.now();
      }
      var tags = result.tags;
      for (var n = tags.length; tagsProcessed < n; tagsProcessed++) {
        var tag = tags[tagsProcessed];
        if ('id' in tag) {
          var symbol = defineSymbol(tag, symbols);
          commitData(symbol, symbol.transferables);
          continue;
        }
        switch (tag.code) {
        case SWF_TAG_CODE_DEFINE_SCENE_AND_FRAME_LABEL_DATA:
          frame.sceneData = tag;
          break;
        case SWF_TAG_CODE_DEFINE_SCALING_GRID:
          var symbolUpdate = {
              isSymbol: true,
              id: tag.symbolId,
              updates: {
                scale9Grid: tag.splitter
              }
            };
          commitData(symbolUpdate);
          break;
        case SWF_TAG_CODE_DO_ABC:
        case SWF_TAG_CODE_DO_ABC_:
          var abcBlocks = frame.abcBlocks;
          if (abcBlocks)
            abcBlocks.push({
              data: tag.data,
              flags: tag.flags
            });
          else
            frame.abcBlocks = [
              {
                data: tag.data,
                flags: tag.flags
              }
            ];
          break;
        case SWF_TAG_CODE_DO_ACTION:
          var actionBlocks = frame.actionBlocks;
          if (actionBlocks)
            actionBlocks.push(tag.actionsData);
          else
            frame.actionBlocks = [
              tag.actionsData
            ];
          break;
        case SWF_TAG_CODE_DO_INIT_ACTION:
          var initActionBlocks = frame.initActionBlocks || (frame.initActionBlocks = []);
          initActionBlocks.push({
            spriteId: tag.spriteId,
            actionsData: tag.actionsData
          });
          break;
        case SWF_TAG_CODE_START_SOUND:
          var startSounds = frame.startSounds;
          if (!startSounds)
            frame.startSounds = startSounds = [];
          startSounds.push(tag);
          break;
        case SWF_TAG_CODE_SOUND_STREAM_HEAD:
          try {
            soundStream = createSoundStream(tag);
            frame.soundStream = soundStream.info;
          } catch (e) {
          }
          break;
        case SWF_TAG_CODE_SOUND_STREAM_BLOCK:
          if (soundStream) {
            frame.soundStreamBlock = soundStream.decode(tag.data);
          }
          break;
        case SWF_TAG_CODE_EXPORT_ASSETS:
          var exports = frame.exports;
          if (exports)
            frame.exports = exports.concat(tag.exports);
          else
            frame.exports = tag.exports.slice(0);
          break;
        case SWF_TAG_CODE_SYMBOL_CLASS:
          var symbolClasses = frame.symbolClasses;
          if (symbolClasses)
            frame.symbolClasses = symbolClasses.concat(tag.exports);
          else
            frame.symbolClasses = tag.exports.slice(0);
          break;
        case SWF_TAG_CODE_FRAME_LABEL:
          frame.labelName = tag.name;
          break;
        case SWF_TAG_CODE_PLACE_OBJECT:
        case SWF_TAG_CODE_PLACE_OBJECT2:
        case SWF_TAG_CODE_PLACE_OBJECT3:
          depths[tag.depth] = tag;
          break;
        case SWF_TAG_CODE_REMOVE_OBJECT:
        case SWF_TAG_CODE_REMOVE_OBJECT2:
          depths[tag.depth] = null;
          break;
        case SWF_TAG_CODE_SET_BACKGROUND_COLOR:
          frame.bgcolor = tag.color;
          break;
        case SWF_TAG_CODE_SHOW_FRAME:
          frame.repeat = tag.repeat;
          frame.depths = depths;
          frame.complete = !(!tag.finalTag);
          commitData(frame);
          depths = {};
          frame = {
            type: 'frame'
          };
          break;
        }
      }
    },
    oncomplete: function (result) {
      commitData(result);
      var stats;
      if (typeof result.swfVersion === 'number') {
        var bbox = result.bbox;
        stats = {
          topic: 'parseInfo',
          parseTime: result.parseTime,
          bytesTotal: result.bytesTotal,
          swfVersion: result.swfVersion,
          frameRate: result.frameRate,
          width: (bbox.xMax - bbox.xMin) / 20,
          height: (bbox.yMax - bbox.yMin) / 20,
          isAvm2: !(!result.fileAttributes.doAbc)
        };
      }
      commitData({
        command: 'complete',
        stats: stats
      });
    },
    onexception: function (e) {
      commitData({
        type: 'exception',
        message: e.message,
        stack: e.stack
      });
    }
  };
}
function parseBytes(bytes, commitData) {
  SWF.parse(bytes, createParsingContext(commitData));
}
function ResourceLoader(scope) {
  this.subscription = null;
  var self = this;
  if (!isWorker) {
    this.messenger = {
      postMessage: function (data) {
        self.onmessage({
          data: data
        });
      }
    };
  } else {
    this.messenger = scope;
    scope.onmessage = function (event) {
      self.listener(event.data);
    };
  }
}
ResourceLoader.prototype = {
  terminate: function () {
    this.messenger = null;
    this.listener = null;
  },
  onmessage: function (event) {
    this.listener(event.data);
  },
  postMessage: function (data) {
    this.listener && this.listener(data);
  },
  listener: function (data) {
    if (this.subscription) {
      this.subscription.callback(data.data, data.progress);
    } else if (data === 'pipe:') {
      this.subscription = {
        subscribe: function (callback) {
          this.callback = callback;
        }
      };
      this.parseLoadedData(this.messenger, this.subscription);
    } else {
      this.parseLoadedData(this.messenger, data);
    }
  },
  parseLoadedData: function (loader, request, context) {
    function commitData(data, transferables) {
      try {
        loader.postMessage(data, transferables);
      } catch (ex) {
        if (ex != 'DataCloneError') {
          throw ex;
        }
        loader.postMessage(data);
      }
    }
    if (request instanceof ArrayBuffer) {
      parseBytes(request, commitData);
    } else if ('subscribe' in request) {
      var pipe = SWF.parseAsync(createParsingContext(commitData));
      request.subscribe(function (data, progress) {
        if (data) {
          pipe.push(data, progress);
        } else {
          pipe.close();
        }
      });
    } else if (typeof FileReaderSync !== 'undefined') {
      var reader = new FileReaderSync();
      var buffer = reader.readAsArrayBuffer(request);
      parseBytes(buffer, commitData);
    } else {
      var reader = new FileReader();
      reader.onload = function () {
        parseBytes(this.result, commitData);
      };
      reader.readAsArrayBuffer(request);
    }
  }
};
if (isWorker) {
  var loader = new ResourceLoader(this);
}
function ActionsDataStream(array, swfVersion) {
  this.array = array;
  this.position = 0;
  this.end = array.length;
  if (swfVersion >= 6) {
    this.readString = this.readUTF8String;
  } else {
    this.readString = this.readANSIString;
  }
  var buffer = new ArrayBuffer(4);
  new Int32Array(buffer)[0] = 1;
  if (!new Uint8Array(buffer)[0]) {
    throw new Error('big-endian platform');
  }
}
ActionsDataStream.prototype = {
  readUI8: function ActionsDataStream_readUI8() {
    return this.array[this.position++];
  },
  readUI16: function ActionsDataStream_readUI16() {
    var position = this.position, array = this.array;
    var value = array[position + 1] << 8 | array[position];
    this.position = position + 2;
    return value;
  },
  readSI16: function ActionsDataStream_readSI16() {
    var position = this.position, array = this.array;
    var value = array[position + 1] << 8 | array[position];
    this.position = position + 2;
    return value < 32768 ? value : value - 65536;
  },
  readInteger: function ActionsDataStream_readInteger() {
    var position = this.position, array = this.array;
    var value = array[position] | array[position + 1] << 8 | array[position + 2] << 16 | array[position + 3] << 24;
    this.position = position + 4;
    return value;
  },
  readFloat: function ActionsDataStream_readFloat() {
    var position = this.position;
    var array = this.array;
    var buffer = new ArrayBuffer(4);
    var bytes = new Uint8Array(buffer);
    bytes[0] = array[position];
    bytes[1] = array[position + 1];
    bytes[2] = array[position + 2];
    bytes[3] = array[position + 3];
    this.position = position + 4;
    return new Float32Array(buffer)[0];
  },
  readDouble: function ActionsDataStream_readDouble() {
    var position = this.position;
    var array = this.array;
    var buffer = new ArrayBuffer(8);
    var bytes = new Uint8Array(buffer);
    bytes[4] = array[position];
    bytes[5] = array[position + 1];
    bytes[6] = array[position + 2];
    bytes[7] = array[position + 3];
    bytes[0] = array[position + 4];
    bytes[1] = array[position + 5];
    bytes[2] = array[position + 6];
    bytes[3] = array[position + 7];
    this.position = position + 8;
    return new Float64Array(buffer)[0];
  },
  readBoolean: function ActionsDataStream_readBoolean() {
    return !(!this.readUI8());
  },
  readANSIString: function ActionsDataStream_readANSIString() {
    var value = '';
    var ch;
    while (ch = this.readUI8()) {
      value += String.fromCharCode(ch);
    }
    return value;
  },
  readUTF8String: function ActionsDataStream_readUTF8String() {
    var value = '';
    var ch;
    while (ch = this.readUI8()) {
      if (ch < 128) {
        value += String.fromCharCode(ch);
        continue;
      }
      if ((ch & 192) === 128) {
        throw new Error('Invalid UTF8 encoding');
      }
      var currentPrefix = 192;
      var validBits = 5;
      do {
        var mask = currentPrefix >> 1 | 128;
        if ((ch & mask) === currentPrefix) {
          break;
        }
        currentPrefix = mask;
        --validBits;
      } while (validBits >= 0);
      var code = ch & (1 << validBits) - 1;
      for (var i = 5; i >= validBits; --i) {
        ch = this.readUI8();
        if ((ch & 192) !== 128) {
          throw new Error('Invalid UTF8 encoding');
        }
        code = code << 6 | ch & 63;
      }
      if (code >= 65536) {
        value += String.fromCharCode(code - 65536 >> 10 & 1023 | 55296, code & 1023 | 56320);
      } else {
        value += String.fromCharCode(code);
      }
    }
    return value;
  },
  readBytes: function ActionsDataStream_readBytes(length) {
    var position = this.position;
    var remaining = Math.max(this.end - position, 0);
    if (remaining < length) {
      length = remaining;
    }
    var subarray = this.array.subarray(position, position + length);
    this.position = position + length;
    return subarray;
  }
};
if (typeof GLOBAL !== 'undefined') {
  GLOBAL.ActionsDataStream = ActionsDataStream;
}
var AVM1_TRACE_ENABLED = false;
var AVM1_ERRORS_IGNORED = true;
var MAX_AVM1_HANG_TIMEOUT = 1000;
var MAX_AVM1_ERRORS_LIMIT = 1000;
var MAX_AVM1_STACK_LIMIT = 256;
function AS2ScopeListItem(scope, next) {
  this.scope = scope;
  this.next = next;
}
AS2ScopeListItem.prototype = {
  create: function (scope) {
    return new AS2ScopeListItem(scope, this);
  }
};
function AS2Context(swfVersion) {
  this.swfVersion = swfVersion;
  this.globals = new avm1lib.AS2Globals(this);
  this.initialScope = new AS2ScopeListItem(this.globals, null);
  this.assets = {};
  this.isActive = false;
  this.executionProhibited = false;
  this.abortExecutionAt = 0;
  this.stackDepth = 0;
  this.isTryCatchListening = false;
  this.errorsIgnored = 0;
  this.deferScriptExecution = true;
  this.pendingScripts = [];
}
AS2Context.instance = null;
AS2Context.prototype = {
  addAsset: function (className, symbolProps) {
    this.assets[className] = symbolProps;
  },
  resolveTarget: function (target) {
    if (!target) {
      target = this.defaultTarget;
    } else if (typeof target === 'string') {
      target = lookupAS2Children(target, this.defaultTarget, this.globals.asGetPublicProperty('_root'));
    }
    if (typeof target !== 'object' || target === null || !('$nativeObject' in target)) {
      throw new Error('Invalid AS2 target object: ' + Object.prototype.toString.call(target));
    }
    return target;
  },
  resolveLevel: function (level) {
    return this.resolveTarget(this.globals['_level' + level]);
  },
  addToPendingScripts: function (fn) {
    if (!this.deferScriptExecution) {
      return fn();
    }
    this.pendingScripts.push(fn);
  },
  flushPendingScripts: function () {
    var scripts = this.pendingScripts;
    while (scripts.length) {
      scripts.shift()();
    }
    this.deferScriptExecution = false;
  }
};
function AS2Error(error) {
  this.error = error;
}
function AS2CriticalError(message, error) {
  this.message = message;
  this.error = error;
}
AS2CriticalError.prototype = Object.create(Error.prototype);
function isAS2MovieClip(obj) {
  return typeof obj === 'object' && obj && obj instanceof avm1lib.AS2MovieClip;
}
function as2GetType(v) {
  if (v === null) {
    return 'null';
  }
  var type = typeof v;
  if (type === 'function') {
    return 'object';
  }
  if (type === 'object' && isAS2MovieClip(v)) {
    return 'movieclip';
  }
  return type;
}
function as2ToPrimitive(value) {
  return as2GetType(value) !== 'object' ? value : value.valueOf();
}
function as2ToAddPrimitive(value) {
  if (as2GetType(value) !== 'object') {
    return value;
  }
  if (value instanceof Date && AS2Context.instance.swfVersion >= 6) {
    return value.toString();
  } else {
    return value.valueOf();
  }
}
function as2ToBoolean(value) {
  switch (as2GetType(value)) {
  default:
  case 'undefined':
  case 'null':
    return false;
  case 'boolean':
    return value;
  case 'number':
    return value !== 0 && !isNaN(value);
  case 'string':
    return value.length !== 0;
  case 'movieclip':
  case 'object':
    return true;
  }
}
function as2ToNumber(value) {
  value = as2ToPrimitive(value);
  switch (as2GetType(value)) {
  case 'undefined':
  case 'null':
    return AS2Context.instance.swfVersion >= 7 ? NaN : 0;
  case 'boolean':
    return value ? 1 : +0;
  case 'number':
    return value;
  case 'string':
    if (value === '' && AS2Context.instance.swfVersion < 5) {
      return 0;
    }
    return +value;
  default:
    return AS2Context.instance.swfVersion >= 5 ? NaN : 0;
  }
}
function as2ToInteger(value) {
  var result = as2ToNumber(value);
  if (isNaN(result)) {
    return 0;
  }
  if (!isFinite(result) || result === 0) {
    return result;
  }
  return (result < 0 ? -1 : 1) * Math.abs(result) | 0;
}
function as2ToInt32(value) {
  var result = as2ToNumber(value);
  return isNaN(result) || !isFinite(result) || result === 0 ? 0 : result | 0;
}
function as2ToString(value) {
  switch (as2GetType(value)) {
  case 'undefined':
    return AS2Context.instance.swfVersion >= 7 ? 'undefined' : '';
  case 'null':
    return 'null';
  case 'boolean':
    return value ? 'true' : 'false';
  case 'number':
    return value.toString();
  case 'string':
    return value;
  case 'movieclip':
    return value.$targetPath;
  case 'object':
    var result = value.toString !== Function.prototype.toString ? value.toString() : value;
    if (typeof result === 'string') {
      return result;
    }
    return typeof value === 'function' ? '[type Function]' : '[type Object]';
  }
}
function as2Compare(x, y) {
  var x2 = as2ToPrimitive(x);
  var y2 = as2ToPrimitive(y);
  if (typeof x2 === 'string' && typeof y2 === 'string') {
    return x2 < y2;
  } else {
    return as2ToNumber(x2) < as2ToNumber(y2);
  }
}
function as2InstanceOf(obj, constructor) {
  if (obj instanceof constructor) {
    return true;
  }
  return false;
}
function as2ResolveProperty(obj, name) {
  var avm2PublicName = Multiname.getPublicQualifiedName(name);
  if (avm2PublicName in obj) {
    return name;
  }
  if (isNumeric(name)) {
    return null;
  }
  var lowerCaseName = avm2PublicName.toLowerCase();
  for (var i in obj) {
    if (i.toLowerCase() === lowerCaseName) {
      notImplemented('FIX THIS');
    }
  }
  return null;
}
function as2GetPrototype(obj) {
  return obj && obj.asGetPublicProperty('prototype');
}
function isAvm2Class(obj) {
  return typeof obj === 'object' && obj !== null && 'instanceConstructor' in obj;
}
function as2CreatePrototypeProxy(obj) {
  var prototype = obj.asGetPublicProperty('prototype');
  if (typeof Proxy === 'undefined') {
    console.error('ES6 proxies are not found');
    return prototype;
  }
  return Proxy.create({
    getOwnPropertyDescriptor: function (name) {
      return Object.getOwnPropertyDescriptor(prototype, name);
    },
    getPropertyDescriptor: function (name) {
      for (var p = prototype; p; p = Object.getPrototypeOf(p)) {
        var desc = Object.getOwnPropertyDescriptor(p, name);
        if (desc)
          return desc;
      }
    },
    getOwnPropertyNames: function () {
      return Object.getOwnPropertyNames(prototype);
    },
    getPropertyNames: function () {
      var names = Object.getOwnPropertyNames(prototype);
      for (var p = Object.getPrototypeOf(prototype); p; p = Object.getPrototypeOf(p)) {
        names = names.concat(Object.getOwnPropertyNames(p));
      }
      return names;
    },
    defineProperty: function (name, desc) {
      if (desc) {
        if (typeof desc.value === 'function' && desc.value._setClass) {
          desc.value._setClass(obj);
        }
        if (typeof desc.get === 'function' && desc.get._setClass) {
          desc.get._setClass(obj);
        }
        if (typeof desc.set === 'function' && desc.set._setClass) {
          desc.set._setClass(obj);
        }
      }
      return Object.defineProperty(prototype, name, desc);
    },
    delete: function (name) {
      return delete prototype[name];
    },
    fix: function () {
      return undefined;
    }
  });
}
function executeActions(actionsData, context, scope) {
  if (context.executionProhibited) {
    return;
  }
  var actionTracer = ActionTracerFactory.get();
  var scopeContainer = context.initialScope.create(scope);
  var savedContext = AS2Context.instance;
  try {
    AS2Context.instance = context;
    context.isActive = true;
    context.abortExecutionAt = Date.now() + MAX_AVM1_HANG_TIMEOUT;
    context.errorsIgnored = 0;
    context.defaultTarget = scope;
    context.globals.asSetPublicProperty('this', scope);
    actionTracer.message('ActionScript Execution Starts');
    actionTracer.indent();
    interpretActions(actionsData, scopeContainer, null, []);
  } catch (e) {
    if (e instanceof AS2CriticalError) {
      console.error('Disabling AVM1 execution');
      context.executionProhibited = true;
    }
    throw e;
  } finally {
    context.isActive = false;
    actionTracer.unindent();
    actionTracer.message('ActionScript Execution Stops');
    AS2Context.instance = savedContext;
  }
}
function lookupAS2Children(targetPath, defaultTarget, root) {
  var path = targetPath.split(/[\/.]/g);
  if (path[path.length - 1] === '') {
    path.pop();
  }
  var obj = defaultTarget;
  if (path[0] === '' || path[0] === '_level0' || path[0] === '_root') {
    obj = root;
    path.shift();
  }
  while (path.length > 0) {
    var prevObj = obj;
    obj = obj.$lookupChild(path[0]);
    if (!obj) {
      throw new Error(path[0] + ' (expr ' + targetPath + ') is not found in ' + prevObj._target);
    }
    path.shift();
  }
  return obj;
}
function createBuiltinType(obj, args) {
  if (obj === Array) {
    var result = args;
    if (args.length == 1 && typeof args[0] === 'number') {
      result = [];
      result.length = args[0];
    }
    return result;
  }
  if (obj === Boolean || obj === Number || obj === String || obj === Function) {
    return obj.apply(null, args);
  }
  if (obj === Date) {
    switch (args.length) {
    case 0:
      return new Date();
    case 1:
      return new Date(args[0]);
    default:
      return new Date(args[0], args[1], args.length > 2 ? args[2] : 1, args.length > 3 ? args[3] : 0, args.length > 4 ? args[4] : 0, args.length > 5 ? args[5] : 0, args.length > 6 ? args[6] : 0);
    }
  }
  if (obj === Object) {
    return {};
  }
}
var AS2_SUPER_STUB = {};
function interpretActions(actionsData, scopeContainer, constantPool, registers) {
  var currentContext = AS2Context.instance;
  function setTarget(targetPath) {
    if (!targetPath) {
      currentContext.defaultTarget = scope;
      return;
    }
    try {
      currentContext.defaultTarget = lookupAS2Children(targetPath, defaultTarget, _global.asGetPublicProperty('_root'));
    } catch (e) {
      currentContext.defaultTarget = null;
      throw e;
    }
  }
  function defineFunction(functionName, parametersNames, registersAllocation, actionsData) {
    var ownerClass;
    var fn = function () {
      var newScope = {};
      newScope.asSetPublicProperty('this', this);
      newScope.asSetPublicProperty('arguments', arguments);
      newScope.asSetPublicProperty('super', AS2_SUPER_STUB);
      newScope.asSetPublicProperty('__class', ownerClass);
      var newScopeContainer = scopeContainer.create(newScope);
      var i;
      for (i = 0; i < arguments.length || i < parametersNames.length; i++) {
        newScope.asSetPublicProperty(parametersNames[i], arguments[i]);
      }
      var registers = [];
      if (registersAllocation) {
        for (i = 0; i < registersAllocation.length; i++) {
          var registerAllocation = registersAllocation[i];
          if (!registerAllocation) {
            continue;
          }
          if (registerAllocation.type == 'param') {
            registers[i] = arguments[registerAllocation.index];
          } else {
            switch (registerAllocation.name) {
            case 'this':
              registers[i] = this;
              break;
            case 'arguments':
              registers[i] = arguments;
              break;
            case 'super':
              registers[i] = AS2_SUPER_STUB;
              break;
            case '_global':
              registers[i] = _global;
              break;
            case '_parent':
              registers[i] = scope.asGetPublicProperty('_parent');
              break;
            case '_root':
              registers[i] = _global.asGetPublicProperty('_root');
              break;
            }
          }
        }
      }
      var savedContext = AS2Context.instance;
      var savedIsActive = currentContext.isActive;
      try {
        AS2Context.instance = currentContext;
        if (!savedIsActive) {
          currentContext.abortExecutionAt = Date.now() + MAX_AVM1_HANG_TIMEOUT;
          currentContext.errorsIgnored = 0;
          currentContext.isActive = true;
        }
        currentContext.defaultTarget = scope;
        actionTracer.indent();
        currentContext.stackDepth++;
        if (currentContext.stackDepth >= MAX_AVM1_STACK_LIMIT) {
          throw new AS2CriticalError('long running script -- AVM1 recursion limit is reached');
        }
        return interpretActions(actionsData, newScopeContainer, constantPool, registers);
      } finally {
        currentContext.isActive = savedIsActive;
        currentContext.stackDepth--;
        actionTracer.unindent();
        currentContext.defaultTarget = defaultTarget;
        AS2Context.instance = savedContext;
      }
    };
    ownerClass = fn;
    fn._setClass = function (class_) {
      ownerClass = class_;
    };
    fn.instanceConstructor = fn;
    fn.debugName = 'avm1 ' + (functionName || '<function>');
    if (functionName) {
      fn.name = functionName;
    }
    return fn;
  }
  function deleteProperty(propertyName) {
    for (var p = scopeContainer; p; p = p.next) {
      if (p.scope.asHasProperty(undefined, propertyName, 0)) {
        p.scope.asSetPublicProperty(propertyName, undefined);
        return p.scope.asDeleteProperty(undefined, propertyName, 0);
      }
    }
    return false;
  }
  function resolveVariableName(variableName, nonStrict) {
    var obj, name, i;
    if (variableName.indexOf(':') >= 0) {
      var parts = variableName.split(':');
      obj = lookupAS2Children(parts[0], defaultTarget, _global.asGetPublicProperty('_root'));
      if (!obj) {
        throw new Error(parts[0] + ' is undefined');
      }
      name = parts[1];
    } else if (variableName.indexOf('.') >= 0) {
      var objPath = variableName.split('.');
      name = objPath.pop();
      obj = _global;
      for (i = 0; i < objPath.length; i++) {
        obj = obj.asGetPublicProperty(objPath[i]) || obj[objPath[i]];
        if (!obj) {
          throw new Error(objPath.slice(0, i + 1) + ' is undefined');
        }
      }
    }
    if (!obj) {
      return null;
    }
    var resolvedName = as2ResolveProperty(obj, name);
    var resolved = resolvedName !== null;
    if (resolved || nonStrict) {
      return {
        obj: obj,
        name: resolvedName || name,
        resolved: resolved
      };
    }
    return null;
  }
  function getThis() {
    var _this = scope.asGetPublicProperty('this');
    if (_this) {
      return _this;
    }
    for (var p = scopeContainer; p; p = p.next) {
      resolvedName = as2ResolveProperty(p.scope, 'this');
      if (resolvedName !== null) {
        return p.scope.asGetPublicProperty(resolvedName);
      }
    }
  }
  function getVariable(variableName) {
    if (scope.asHasProperty(undefined, variableName, 0)) {
      return scope.asGetPublicProperty(variableName);
    }
    var target = resolveVariableName(variableName);
    if (target) {
      return target.obj.asGetPublicProperty(target.name);
    }
    var resolvedName, _this = getThis();
    for (var p = scopeContainer; p; p = p.next) {
      resolvedName = as2ResolveProperty(p.scope, variableName);
      if (resolvedName !== null) {
        return p.scope.asGetPublicProperty(resolvedName);
      }
    }
    if (_this && (resolvedName = as2ResolveProperty(_this, variableName))) {
      return _this.asGetPublicProperty(resolvedName);
    }
    var mc = isAS2MovieClip(defaultTarget) && defaultTarget.$lookupChild(variableName);
    if (mc) {
      return mc;
    }
  }
  function setVariable(variableName, value) {
    if (scope.asHasProperty(undefined, variableName, 0)) {
      scope.asSetPublicProperty(variableName, value);
      return;
    }
    var target = resolveVariableName(variableName, true);
    if (target) {
      target.obj.asSetPublicProperty(target.name, value);
      return;
    }
    var resolvedName, _this = getThis();
    if (_this && (resolvedName = as2ResolveProperty(_this, variableName))) {
      return _this.asSetPublicProperty(resolvedName, value);
    }
    for (var p = scopeContainer; p.next; p = p.next) {
      resolvedName = as2ResolveProperty(p.scope, variableName);
      if (resolvedName !== null) {
        return p.scope.asSetPublicProperty(resolvedName, value);
      }
    }
    (_this || scope).asSetPublicProperty(variableName, value);
  }
  function getFunction(functionName) {
    var fn = getVariable(functionName);
    if (!(fn instanceof Function)) {
      throw new Error('Function "' + functionName + '" is not found');
    }
    return fn;
  }
  function getObjectByName(objectName) {
    var obj = getVariable(objectName);
    if (!(obj instanceof Object)) {
      throw new Error('Object "' + objectName + '" is not found');
    }
    return obj;
  }
  function processWith(obj, withBlock) {
    var newScopeContainer = scopeContainer.create(Object(obj));
    interpretActions(withBlock, newScopeContainer, constantPool, registers);
  }
  function processTry(catchIsRegisterFlag, finallyBlockFlag, catchBlockFlag, catchTarget, tryBlock, catchBlock, finallyBlock) {
    var savedTryCatchState = currentContext.isTryCatchListening;
    try {
      currentContext.isTryCatchListening = true;
      interpretActions(tryBlock, scopeContainer, constantPool, registers);
    } catch (e) {
      currentContext.isTryCatchListening = savedTryCatchState;
      if (!catchBlockFlag) {
        throw e;
      }
      if (!(e instanceof AS2Error)) {
        throw e;
      }
      if (typeof catchTarget === 'string') {
        scope[catchTarget] = e.error;
      } else {
        registers[catchTarget] = e.error;
      }
      interpretActions(catchBlock, scopeContainer, constantPool, registers);
    } finally {
      currentContext.isTryCatchListening = savedTryCatchState;
      if (finallyBlockFlag) {
        interpretActions(finallyBlock, scopeContainer, constantPool, registers);
      }
    }
  }
  function validateArgsCount(numArgs, maxAmount) {
    if (isNaN(numArgs) || numArgs < 0 || numArgs > maxAmount || numArgs != (0 | numArgs)) {
      throw new Error('Invalid number of arguments: ' + numArgs);
    }
  }
  function readArgs(stack) {
    var numArgs = +stack.pop();
    validateArgsCount(numArgs, stack.length);
    var args = [];
    for (var i = 0; i < numArgs; i++) {
      args.push(stack.pop());
    }
    return args;
  }
  var stream = new ActionsDataStream(actionsData, currentContext.swfVersion);
  var _global = currentContext.globals;
  var defaultTarget = currentContext.defaultTarget;
  var stack = [];
  var scope = scopeContainer.scope;
  var isSwfVersion5 = currentContext.swfVersion >= 5;
  var actionTracer = ActionTracerFactory.get();
  var nextPosition;
  if (scope.$nativeObject && scope.$nativeObject._deferScriptExecution) {
    currentContext.deferScriptExecution = true;
  }
  function skipActions(count) {
    while (count > 0 && stream.position < stream.end) {
      var actionCode = stream.readUI8();
      var length = actionCode >= 128 ? stream.readUI16() : 0;
      stream.position += length;
      count--;
    }
    nextPosition = stream.position;
  }
  var recoveringFromError = false;
  var stackItemsExpected;
  while (stream.position < stream.end) {
    try {
      var instructionsExecuted = 0;
      var abortExecutionAt = currentContext.abortExecutionAt;
      while (stream.position < stream.end) {
        if (instructionsExecuted++ % 100 === 0 && Date.now() >= abortExecutionAt) {
          throw new AS2CriticalError('long running script -- AVM1 instruction hang timeout');
        }
        var actionCode = stream.readUI8();
        var length = actionCode >= 128 ? stream.readUI16() : 0;
        nextPosition = stream.position + length;
        stackItemsExpected = 0;
        actionTracer.print(stream.position, actionCode, stack);
        var frame, type, count, index, target, method, constr, codeSize, offset;
        var name, variableName, methodName, functionName, targetName;
        var paramName, resolvedName, objectName;
        var value, a, b, c, f, sa, sb, obj, args, fn, result, flags, i;
        var dragParams, register;
        switch (actionCode | 0) {
        case 129:
          frame = stream.readUI16();
          var nextActionCode = stream.readUI8();
          nextPosition++;
          methodName = nextActionCode === 6 ? 'gotoAndPlay' : 'gotoAndStop';
          _global[methodName](frame + 1);
          break;
        case 131:
          var urlString = stream.readString();
          var targetString = stream.readString();
          _global.getURL(urlString, targetString);
          break;
        case 4:
          _global.nextFrame();
          break;
        case 5:
          _global.prevFrame();
          break;
        case 6:
          _global.play();
          break;
        case 7:
          _global.stop();
          break;
        case 8:
          _global.toggleHighQuality();
          break;
        case 9:
          _global.stopAllSounds();
          break;
        case 138:
          frame = stream.readUI16();
          count = stream.readUI8();
          if (!_global.ifFrameLoaded(frame)) {
            skipActions(count);
          }
          break;
        case 139:
          targetName = stream.readString();
          setTarget(targetName);
          break;
        case 140:
          var label = stream.readString();
          _global.gotoLabel(label);
          break;
        case 150:
          while (stream.position < nextPosition) {
            type = stream.readUI8();
            switch (type) {
            case 0:
              value = stream.readString();
              break;
            case 1:
              value = stream.readFloat();
              break;
            case 2:
              value = null;
              break;
            case 3:
              value = void 0;
              break;
            case 4:
              value = registers[stream.readUI8()];
              break;
            case 5:
              value = stream.readBoolean();
              break;
            case 6:
              value = stream.readDouble();
              break;
            case 7:
              value = stream.readInteger();
              break;
            case 8:
              value = constantPool[stream.readUI8()];
              break;
            case 9:
              value = constantPool[stream.readUI16()];
              break;
            default:
              throw new Error('Unknown value type: ' + type);
            }
            stack.push(value);
          }
          break;
        case 23:
          stack.pop();
          break;
        case 10:
          a = as2ToNumber(stack.pop());
          b = as2ToNumber(stack.pop());
          stack.push(a + b);
          break;
        case 11:
          a = as2ToNumber(stack.pop());
          b = as2ToNumber(stack.pop());
          stack.push(b - a);
          break;
        case 12:
          a = as2ToNumber(stack.pop());
          b = as2ToNumber(stack.pop());
          stack.push(a * b);
          break;
        case 13:
          a = as2ToNumber(stack.pop());
          b = as2ToNumber(stack.pop());
          c = b / a;
          stack.push(isSwfVersion5 ? c : isFinite(c) ? c : '#ERROR#');
          break;
        case 14:
          a = as2ToNumber(stack.pop());
          b = as2ToNumber(stack.pop());
          f = a == b;
          stack.push(isSwfVersion5 ? f : f ? 1 : 0);
          break;
        case 15:
          a = as2ToNumber(stack.pop());
          b = as2ToNumber(stack.pop());
          f = b < a;
          stack.push(isSwfVersion5 ? f : f ? 1 : 0);
          break;
        case 16:
          a = as2ToBoolean(stack.pop());
          b = as2ToBoolean(stack.pop());
          f = a && b;
          stack.push(isSwfVersion5 ? f : f ? 1 : 0);
          break;
        case 17:
          a = as2ToBoolean(stack.pop());
          b = as2ToBoolean(stack.pop());
          f = a || b;
          stack.push(isSwfVersion5 ? f : f ? 1 : 0);
          break;
        case 18:
          f = !as2ToBoolean(stack.pop());
          stack.push(isSwfVersion5 ? f : f ? 1 : 0);
          break;
        case 19:
          sa = as2ToString(stack.pop());
          sb = as2ToString(stack.pop());
          f = sa == sb;
          stack.push(isSwfVersion5 ? f : f ? 1 : 0);
          break;
        case 20:
        case 49:
          sa = as2ToString(stack.pop());
          stack.push(_global.length(sa));
          break;
        case 33:
          sa = as2ToString(stack.pop());
          sb = as2ToString(stack.pop());
          stack.push(sb + sa);
          break;
        case 21:
          count = stack.pop();
          index = stack.pop();
          value = as2ToString(stack.pop());
          stack.push(_global.substring(value, index, count));
          break;
        case 53:
          count = stack.pop();
          index = stack.pop();
          value = as2ToString(stack.pop());
          stack.push(_global.mbsubstring(value, index, count));
          break;
        case 41:
          sa = as2ToString(stack.pop());
          sb = as2ToString(stack.pop());
          f = sb < sa;
          stack.push(isSwfVersion5 ? f : f ? 1 : 0);
          break;
        case 24:
          stack.push(_global.int(stack.pop()));
          break;
        case 50:
          stack.push(_global.chr(stack.pop()));
          break;
        case 54:
          stack.push(_global.mbchr(stack.pop()));
          break;
        case 51:
          stack.push(_global.ord(stack.pop()));
          break;
        case 55:
          stack.push(_global.mbord(stack.pop()));
          break;
        case 153:
          offset = stream.readSI16();
          nextPosition += offset;
          break;
        case 157:
          offset = stream.readSI16();
          f = !(!stack.pop());
          if (f) {
            nextPosition += offset;
          }
          break;
        case 158:
          label = stack.pop();
          _global.call(label);
          break;
        case 28:
          variableName = '' + stack.pop();
          stackItemsExpected++;
          stack.push(getVariable(variableName));
          break;
        case 29:
          value = stack.pop();
          variableName = '' + stack.pop();
          setVariable(variableName, value);
          break;
        case 154:
          flags = stream.readUI8();
          target = stack.pop();
          var url = stack.pop();
          var sendVarsMethod;
          if (flags & 1) {
            sendVarsMethod = 'GET';
          } else if (flags & 2) {
            sendVarsMethod = 'POST';
          }
          var loadTargetFlag = flags & 1 << 6;
          if (!loadTargetFlag) {
            _global.getURL(url, target, sendVarsMethod);
            break;
          }
          var loadVariablesFlag = flags & 1 << 7;
          if (loadVariablesFlag) {
            _global.loadVariables(url, target, sendVarsMethod);
          } else {
            _global.loadMovie(url, target, sendVarsMethod);
          }
          break;
        case 159:
          flags = stream.readUI8();
          var gotoParams = [
              stack.pop()
            ];
          if (!(!(flags & 2))) {
            gotoParams.push(stream.readUI16());
          }
          var gotoMethod = !(!(flags & 1)) ? _global.gotoAndPlay : _global.gotoAndStop;
          gotoMethod.apply(_global, gotoParams);
          break;
        case 32:
          target = stack.pop();
          setTarget(target);
          break;
        case 34:
          index = stack.pop();
          target = stack.pop();
          stackItemsExpected++;
          stack.push(_global.getAS2Property(target, index));
          break;
        case 35:
          value = stack.pop();
          index = stack.pop();
          target = stack.pop();
          _global.setAS2Property(target, index, value);
          break;
        case 36:
          var depth = stack.pop();
          target = stack.pop();
          var source = stack.pop();
          _global.duplicateMovieClip(source, target, depth);
          break;
        case 37:
          target = stack.pop();
          _global.removeMovieClip(target);
          break;
        case 39:
          target = stack.pop();
          var lockcenter = stack.pop();
          var constrain = !stack.pop() ? null : {
              y2: stack.pop(),
              x2: stack.pop(),
              y1: stack.pop(),
              x1: stack.pop()
            };
          dragParams = [
            target,
            lockcenter
          ];
          if (constrain) {
            dragParams = dragParams.push(constrain.x1, constrain.y1, constrain.x2, constrain.y2);
          }
          _global.startDrag.apply(_global, dragParams);
          break;
        case 40:
          _global.stopDrag();
          break;
        case 141:
          count = stream.readUI8();
          frame = stack.pop();
          if (!_global.ifFrameLoaded(frame)) {
            skipActions(count);
          }
          break;
        case 38:
          value = stack.pop();
          _global.trace(value);
          break;
        case 52:
          stack.push(_global.getTimer());
          break;
        case 48:
          stack.push(_global.random(stack.pop()));
          break;
        case 61:
          functionName = stack.pop();
          args = readArgs(stack);
          stackItemsExpected++;
          fn = getFunction(functionName);
          result = fn.apply(scope, args);
          stack.push(result);
          break;
        case 82:
          methodName = stack.pop();
          obj = stack.pop();
          args = readArgs(stack);
          stackItemsExpected++;
          if (methodName !== null && methodName !== undefined && methodName !== '') {
            if (obj === null || obj === undefined) {
              throw new Error('Cannot call method ' + methodName + ' of ' + typeof obj);
            } else if (obj !== AS2_SUPER_STUB) {
              target = Object(obj);
            } else {
              target = as2GetPrototype(getVariable('__class').__super);
              obj = getVariable('this');
            }
            resolvedName = as2ResolveProperty(target, methodName);
            if (resolvedName === null) {
              throw new Error('Method ' + methodName + ' is not defined.');
            }
            result = target.asGetPublicProperty(resolvedName).apply(obj, args);
          } else if (obj !== AS2_SUPER_STUB) {
            result = obj.apply(obj, args);
          } else {
            result = getVariable('__class').__super.apply(getVariable('this'), args);
          }
          stack.push(result);
          break;
        case 136:
          count = stream.readUI16();
          constantPool = [];
          for (i = 0; i < count; i++) {
            constantPool.push(stream.readString());
          }
          break;
        case 155:
          functionName = stream.readString();
          count = stream.readUI16();
          args = [];
          for (i = 0; i < count; i++) {
            args.push(stream.readString());
          }
          codeSize = stream.readUI16();
          nextPosition += codeSize;
          fn = defineFunction(functionName, args, null, stream.readBytes(codeSize));
          if (functionName) {
            scope.asSetPublicProperty(functionName, fn);
          } else {
            stack.push(fn);
          }
          break;
        case 60:
          value = stack.pop();
          name = stack.pop();
          scope.asSetPublicProperty(name, value);
          break;
        case 65:
          name = stack.pop();
          scope.asSetPublicProperty(name, undefined);
          break;
        case 58:
          name = stack.pop();
          obj = stack.pop();
          obj.asSetPublicProperty(name, undefined);
          stack.push(obj.asDeleteProperty(undefined, name, 0));
          break;
        case 59:
          name = stack.pop();
          result = deleteProperty(name);
          stack.push(result);
          break;
        case 70:
          objectName = stack.pop();
          stack.push(null);
          obj = getObjectByName(objectName);
          forEachPublicProperty(obj, function (name) {
            stack.push(name);
          });
          break;
        case 73:
          a = stack.pop();
          b = stack.pop();
          stack.push(a == b);
          break;
        case 78:
          name = stack.pop();
          obj = stack.pop();
          if (name === 'prototype') {
            stack.push(as2CreatePrototypeProxy(obj));
          } else {
            resolvedName = as2ResolveProperty(Object(obj), name);
            stack.push(resolvedName === null ? undefined : obj.asGetPublicProperty(resolvedName));
          }
          break;
        case 66:
          obj = readArgs(stack);
          stack.push(obj);
          break;
        case 67:
          count = +stack.pop();
          validateArgsCount(count, stack.length >> 1);
          obj = {};
          for (i = 0; i < count; i++) {
            value = stack.pop();
            name = stack.pop();
            obj.asSetPublicProperty(name, value);
          }
          stack.push(obj);
          break;
        case 83:
          methodName = stack.pop();
          obj = stack.pop();
          args = readArgs(stack);
          stackItemsExpected++;
          if (methodName !== null && methodName !== undefined && methodName !== '') {
            resolvedName = as2ResolveProperty(obj, methodName);
            if (resolvedName === null) {
              throw new Error('Method ' + methodName + ' is not defined.');
            }
            if (obj === null || obj === undefined) {
              throw new Error('Cannot call new using method ' + resolvedName + ' of ' + typeof obj);
            }
            method = obj.asGetPublicProperty(resolvedName);
          } else {
            if (obj === null || obj === undefined) {
              throw new Error('Cannot call new using ' + typeof obj);
            }
            method = obj;
          }
          if (isAvm2Class(obj)) {
            result = construct(obj, args);
          } else {
            result = Object.create(as2GetPrototype(method) || as2GetPrototype(Object));
            method.apply(result, args);
          }
          result.constructor = method;
          stack.push(result);
          break;
        case 64:
          objectName = stack.pop();
          obj = getObjectByName(objectName);
          args = readArgs(stack);
          stackItemsExpected++;
          result = createBuiltinType(obj, args);
          if (typeof result === 'undefined') {
            if (isAvm2Class(obj)) {
              result = construct(obj, args);
            } else {
              result = Object.create(as2GetPrototype(obj) || as2GetPrototype(Object));
              obj.apply(result, args);
            }
            result.constructor = obj;
          }
          stack.push(result);
          break;
        case 79:
          value = stack.pop();
          name = stack.pop();
          obj = stack.pop();
          obj.asSetPublicProperty(name, value);
          break;
        case 69:
          obj = stack.pop();
          stack.push(as2GetType(obj) === 'movieclip' ? obj._target : void 0);
          break;
        case 148:
          codeSize = stream.readUI16();
          obj = stack.pop();
          nextPosition += codeSize;
          processWith(obj, stream.readBytes(codeSize));
          break;
        case 74:
          stack.push(as2ToNumber(stack.pop()));
          break;
        case 75:
          stack.push(as2ToString(stack.pop()));
          break;
        case 68:
          obj = stack.pop();
          result = as2GetType(obj);
          stack.push(result);
          break;
        case 71:
          a = as2ToAddPrimitive(stack.pop());
          b = as2ToAddPrimitive(stack.pop());
          if (typeof a === 'string' || typeof b === 'string') {
            stack.push(as2ToString(b) + as2ToString(a));
          } else {
            stack.push(as2ToNumber(b) + as2ToNumber(a));
          }
          break;
        case 72:
          a = stack.pop();
          b = stack.pop();
          stack.push(as2Compare(b, a));
          break;
        case 63:
          a = as2ToNumber(stack.pop());
          b = as2ToNumber(stack.pop());
          stack.push(b % a);
          break;
        case 96:
          a = as2ToInt32(stack.pop());
          b = as2ToInt32(stack.pop());
          stack.push(b & a);
          break;
        case 99:
          a = as2ToInt32(stack.pop());
          b = as2ToInt32(stack.pop());
          stack.push(b << a);
          break;
        case 97:
          a = as2ToInt32(stack.pop());
          b = as2ToInt32(stack.pop());
          stack.push(b | a);
          break;
        case 100:
          a = as2ToInt32(stack.pop());
          b = as2ToInt32(stack.pop());
          stack.push(b >> a);
          break;
        case 101:
          a = as2ToInt32(stack.pop());
          b = as2ToInt32(stack.pop());
          stack.push(b >>> a);
          break;
        case 98:
          a = as2ToInt32(stack.pop());
          b = as2ToInt32(stack.pop());
          stack.push(b ^ a);
          break;
        case 81:
          a = as2ToNumber(stack.pop());
          a--;
          stack.push(a);
          break;
        case 80:
          a = as2ToNumber(stack.pop());
          a++;
          stack.push(a);
          break;
        case 76:
          stack.push(stack[stack.length - 1]);
          break;
        case 62:
          return stack.pop();
        case 77:
          stack.push(stack.pop(), stack.pop());
          break;
        case 135:
          register = stream.readUI8();
          registers[register] = stack[stack.length - 1];
          break;
        case 84:
          constr = stack.pop();
          obj = stack.pop();
          stack.push(as2InstanceOf(Object(obj), constr));
          break;
        case 85:
          obj = stack.pop();
          stack.push(null);
          forEachPublicProperty(obj, function (name) {
            stack.push(name);
          });
          break;
        case 102:
          a = stack.pop();
          b = stack.pop();
          stack.push(b === a);
          break;
        case 103:
          a = stack.pop();
          b = stack.pop();
          stack.push(as2Compare(a, b));
          break;
        case 104:
          sa = as2ToString(stack.pop());
          sb = as2ToString(stack.pop());
          f = sb > sa;
          stack.push(isSwfVersion5 ? f : f ? 1 : 0);
          break;
        case 142:
          functionName = stream.readString();
          count = stream.readUI16();
          var registerCount = stream.readUI8();
          flags = stream.readUI16();
          var registerAllocation = [];
          args = [];
          for (i = 0; i < count; i++) {
            register = stream.readUI8();
            paramName = stream.readString();
            args.push(paramName);
            if (register) {
              registerAllocation[register] = {
                type: 'param',
                name: paramName,
                index: i
              };
            }
          }
          codeSize = stream.readUI16();
          nextPosition += codeSize;
          var j = 1;
          if (flags & 1) {
            registerAllocation[j++] = {
              type: 'var',
              name: 'this'
            };
          }
          if (flags & 4) {
            registerAllocation[j++] = {
              type: 'var',
              name: 'arguments'
            };
          }
          if (flags & 16) {
            registerAllocation[j++] = {
              type: 'var',
              name: 'super'
            };
          }
          if (flags & 64) {
            registerAllocation[j++] = {
              type: 'var',
              name: '_root'
            };
          }
          if (flags & 128) {
            registerAllocation[j++] = {
              type: 'var',
              name: '_parent'
            };
          }
          if (flags & 256) {
            registerAllocation[j++] = {
              type: 'var',
              name: '_global'
            };
          }
          fn = defineFunction(functionName, args, registerAllocation, stream.readBytes(codeSize));
          if (functionName) {
            scope.asSetPublicProperty(functionName, fn);
          } else {
            stack.push(fn);
          }
          break;
        case 105:
          var constrSuper = stack.pop();
          constr = stack.pop();
          obj = Object.create(constrSuper.traitsPrototype || as2GetPrototype(constrSuper), {
            constructor: {
              value: constr,
              enumerable: false
            }
          });
          constr.__super = constrSuper;
          constr.prototype = obj;
          break;
        case 43:
          obj = stack.pop();
          constr = stack.pop();
          stack.push(as2InstanceOf(obj, constr) ? obj : null);
          break;
        case 44:
          constr = stack.pop();
          count = +stack.pop();
          validateArgsCount(count, stack.length);
          var interfaces = [];
          for (i = 0; i < count; i++) {
            interfaces.push(stack.pop());
          }
          constr.$interfaces = interfaces;
          break;
        case 143:
          flags = stream.readUI8();
          var catchIsRegisterFlag = !(!(flags & 4));
          var finallyBlockFlag = !(!(flags & 2));
          var catchBlockFlag = !(!(flags & 1));
          var trySize = stream.readUI16();
          var catchSize = stream.readUI16();
          var finallySize = stream.readUI16();
          var catchTarget = catchIsRegisterFlag ? stream.readUI8() : stream.readString();
          nextPosition += trySize + catchSize + finallySize;
          processTry(catchIsRegisterFlag, finallyBlockFlag, catchBlockFlag, catchTarget, stream.readBytes(trySize), stream.readBytes(catchSize), stream.readBytes(finallySize));
          break;
        case 42:
          obj = stack.pop();
          throw new AS2Error(obj);
        case 45:
          args = readArgs(stack);
          stackItemsExpected++;
          result = _global.fscommand.apply(null, args);
          stack.push(result);
          break;
        case 137:
          var mode = stream.readUI8();
          break;
        case 0:
          return;
        default:
          throw new Error('Unknown action code: ' + actionCode);
        }
        stream.position = nextPosition;
        recoveringFromError = false;
      }
    } catch (e) {
      if (!AVM1_ERRORS_IGNORED && !currentContext.isTryCatchListening || e instanceof AS2CriticalError) {
        throw e;
      }
      if (e instanceof AS2Error) {
        throw e;
      }
      var AVM1_ERROR_TYPE = 1;
      TelemetryService.reportTelemetry({
        topic: 'error',
        error: AVM1_ERROR_TYPE
      });
      stream.position = nextPosition;
      if (stackItemsExpected > 0) {
        while (stackItemsExpected--) {
          stack.push(undefined);
        }
      }
      if (!recoveringFromError) {
        if (currentContext.errorsIgnored++ >= MAX_AVM1_ERRORS_LIMIT) {
          throw new AS2CriticalError('long running script -- AVM1 errors limit is reached');
        }
        console.error('AVM1 error: ' + e);
        avm2.exceptions.push({
          source: 'avm1',
          message: e.message,
          stack: e.stack
        });
        recoveringFromError = true;
      }
    }
  }
}
var ActionTracerFactory = function () {
    var indentation = 0;
    var tracer = {
        print: function (position, actionCode, stack) {
          var stackDump = [];
          for (var q = 0; q < stack.length; q++) {
            var item = stack[q];
            stackDump.push(item && typeof item === 'object' ? '[' + (item.constructor && item.constructor.name ? item.constructor.name : 'Object') + ']' : item);
          }
          var indent = new Array(indentation + 1).join('..');
          console.log('AVM1 trace: ' + indent + position + ': ' + ActionNamesMap[actionCode] + '(' + actionCode.toString(16) + '), ' + 'stack=' + stackDump);
        },
        indent: function () {
          indentation++;
        },
        unindent: function () {
          indentation--;
        },
        message: function (str) {
          console.log('AVM1 trace: ------- ' + str);
        }
      };
    var nullTracer = {
        print: function () {
        },
        indent: function () {
        },
        unindent: function () {
        },
        message: function () {
        }
      };
    function ActionTracerFactory() {
    }
    ActionTracerFactory.get = function () {
      return AVM1_TRACE_ENABLED ? tracer : nullTracer;
    };
    return ActionTracerFactory;
  }();
var ActionNamesMap = {
    0: 'EOA',
    4: 'ActionNextFrame',
    5: 'ActionPreviousFrame',
    6: 'ActionPlay',
    7: 'ActionStop',
    8: 'ActionToggleQuality',
    9: 'ActionStopSounds',
    10: 'ActionAdd',
    11: 'ActionSubtract',
    12: 'ActionMultiply',
    13: 'ActionDivide',
    14: 'ActionEquals',
    15: 'ActionLess',
    16: 'ActionAnd',
    17: 'ActionOr',
    18: 'ActionNot',
    19: 'ActionStringEquals',
    20: 'ActionStringLength',
    21: 'ActionStringExtract',
    23: 'ActionPop',
    24: 'ActionToInteger',
    28: 'ActionGetVariable',
    29: 'ActionSetVariable',
    32: 'ActionSetTarget2',
    33: 'ActionStringAdd',
    34: 'ActionGetProperty',
    35: 'ActionSetProperty',
    36: 'ActionCloneSprite',
    37: 'ActionRemoveSprite',
    38: 'ActionTrace',
    39: 'ActionStartDrag',
    40: 'ActionEndDrag',
    41: 'ActionStringLess',
    42: 'ActionThrow',
    43: 'ActionCastOp',
    44: 'ActionImplementsOp',
    45: 'ActionFSCommand2',
    48: 'ActionRandomNumber',
    49: 'ActionMBStringLength',
    50: 'ActionCharToAscii',
    51: 'ActionAsciiToChar',
    52: 'ActionGetTime',
    53: 'ActionMBStringExtrac',
    54: 'ActionMBCharToAscii',
    55: 'ActionMBAsciiToChar',
    58: 'ActionDelete',
    59: 'ActionDelete2',
    60: 'ActionDefineLocal',
    61: 'ActionCallFunction',
    62: 'ActionReturn',
    63: 'ActionModulo',
    64: 'ActionNewObject',
    65: 'ActionDefineLocal2',
    66: 'ActionInitArray',
    67: 'ActionInitObject',
    68: 'ActionTypeOf',
    69: 'ActionTargetPath',
    70: 'ActionEnumerate',
    71: 'ActionAdd2',
    72: 'ActionLess2',
    73: 'ActionEquals2',
    74: 'ActionToNumber',
    75: 'ActionToString',
    76: 'ActionPushDuplicate',
    77: 'ActionStackSwap',
    78: 'ActionGetMember',
    79: 'ActionSetMember',
    80: 'ActionIncrement',
    81: 'ActionDecrement',
    82: 'ActionCallMethod',
    83: 'ActionNewMethod',
    84: 'ActionInstanceOf',
    85: 'ActionEnumerate2',
    96: 'ActionBitAnd',
    97: 'ActionBitOr',
    98: 'ActionBitXor',
    99: 'ActionBitLShift',
    100: 'ActionBitRShift',
    101: 'ActionBitURShift',
    102: 'ActionStrictEquals',
    103: 'ActionGreater',
    104: 'ActionStringGreater',
    105: 'ActionExtends',
    129: 'ActionGotoFrame',
    131: 'ActionGetURL',
    135: 'ActionStoreRegister',
    136: 'ActionConstantPool',
    137: 'ActionStrictMode',
    138: 'ActionWaitForFrame',
    139: 'ActionSetTarget',
    140: 'ActionGoToLabel',
    141: 'ActionWaitForFrame2',
    142: 'ActionDefineFunction',
    143: 'ActionTry',
    148: 'ActionWith',
    150: 'ActionPush',
    153: 'ActionJump',
    154: 'ActionGetURL2',
    155: 'ActionDefineFunction',
    157: 'ActionIf',
    158: 'ActionCall',
    159: 'ActionGotoFrame2'
  };
if (typeof GLOBAL !== 'undefined') {
  GLOBAL.createBuiltinType = createBuiltinType;
  GLOBAL.executeActions = executeActions;
  GLOBAL.AS2Context = AS2Context;
}
var jsGlobal = function () {
    return this || (1, eval)('this');
  }();
var inBrowser = typeof console != 'undefined';
var release = true;
var debug = !true;
if (!jsGlobal.performance) {
  jsGlobal.performance = {};
}
if (!jsGlobal.performance.now) {
  jsGlobal.performance.now = dateNow;
}
function log(message) {
  var optionalParams = [];
  for (var _i = 0; _i < arguments.length - 1; _i++) {
    optionalParams[_i] = arguments[_i + 1];
  }
  jsGlobal.print(message);
}
function warn(message) {
  var optionalParams = [];
  for (var _i = 0; _i < arguments.length - 1; _i++) {
    optionalParams[_i] = arguments[_i + 1];
  }
  if (inBrowser) {
    console.warn(message);
  } else {
    jsGlobal.print(message);
  }
}
var Shumway;
(function (Shumway) {
  (function (CharacterCodes) {
    CharacterCodes[CharacterCodes['_0'] = 48] = '_0';
    CharacterCodes[CharacterCodes['_1'] = 49] = '_1';
    CharacterCodes[CharacterCodes['_2'] = 50] = '_2';
    CharacterCodes[CharacterCodes['_3'] = 51] = '_3';
    CharacterCodes[CharacterCodes['_4'] = 52] = '_4';
    CharacterCodes[CharacterCodes['_5'] = 53] = '_5';
    CharacterCodes[CharacterCodes['_6'] = 54] = '_6';
    CharacterCodes[CharacterCodes['_7'] = 55] = '_7';
    CharacterCodes[CharacterCodes['_8'] = 56] = '_8';
    CharacterCodes[CharacterCodes['_9'] = 57] = '_9';
  }(Shumway.CharacterCodes || (Shumway.CharacterCodes = {})));
  var CharacterCodes = Shumway.CharacterCodes;
  Shumway.UINT32_CHAR_BUFFER_LENGTH = 10;
  Shumway.UINT32_MAX = 4294967295;
  Shumway.UINT32_MAX_DIV_10 = 429496729;
  Shumway.UINT32_MAX_MOD_10 = 5;
  function isString(value) {
    return typeof value === 'string';
  }
  Shumway.isString = isString;
  function isFunction(value) {
    return typeof value === 'function';
  }
  Shumway.isFunction = isFunction;
  function isNumber(value) {
    return typeof value === 'number';
  }
  Shumway.isNumber = isNumber;
  function isNumberOrString(value) {
    return typeof value === 'number' || typeof value === 'string';
  }
  Shumway.isNumberOrString = isNumberOrString;
  function isObject(value) {
    return typeof value === 'object' || typeof value === 'function';
  }
  Shumway.isObject = isObject;
  function toNumber(x) {
    return +x;
  }
  Shumway.toNumber = toNumber;
  function isNumericString(value) {
    return String(Number(value)) === value;
  }
  Shumway.isNumericString = isNumericString;
  function isNumeric(value) {
    if (typeof value === 'number') {
      return true;
    } else if (typeof value === 'string') {
      return isIndex(value) || isNumericString(value);
    } else {
      Debug.notImplemented(typeof value);
    }
  }
  Shumway.isNumeric = isNumeric;
  function isIndex(value) {
    var index = 0;
    if (typeof value === 'number') {
      index = value | 0;
      if (value === index && index >= 0) {
        return true;
      }
      return value >>> 0 === value;
    }
    if (typeof value !== 'string') {
      return false;
    }
    var length = value.length;
    if (length === 0) {
      return false;
    }
    if (value === '0') {
      return true;
    }
    if (length > Shumway.UINT32_CHAR_BUFFER_LENGTH) {
      return false;
    }
    var i = 0;
    index = value.charCodeAt(i++) - 48;
    if (index < 1 || index > 9) {
      return false;
    }
    var oldIndex = 0;
    var c = 0;
    while (i < length) {
      c = value.charCodeAt(i++) - 48;
      if (c < 0 || c > 9) {
        return false;
      }
      oldIndex = index;
      index = 10 * index + c;
    }
    if (oldIndex < Shumway.UINT32_MAX_DIV_10 || oldIndex === Shumway.UINT32_MAX_DIV_10 && c <= Shumway.UINT32_MAX_MOD_10) {
      return true;
    }
    return false;
  }
  Shumway.isIndex = isIndex;
  function isNullOrUndefined(value) {
    return value == undefined;
  }
  Shumway.isNullOrUndefined = isNullOrUndefined;
  (function (Debug) {
    function backtrace() {
      try {
        throw new Error();
      } catch (e) {
        return e.stack ? e.stack.split('\n').slice(2).join('\n') : '';
      }
    }
    Debug.backtrace = backtrace;
    function error(message) {
      if (!inBrowser) {
        warn(Debug.backtrace());
      }
      throw new Error(message);
    }
    Debug.error = error;
    function assert(condition) {
      var args = [];
      for (var _i = 0; _i < arguments.length - 1; _i++) {
        args[_i] = arguments[_i + 1];
      }
      if (condition === '') {
        condition = true;
      }
      if (!condition) {
        var message = Array.prototype.slice.call(arguments);
        message.shift();
        Debug.error(message.join(''));
      }
    }
    Debug.assert = assert;
    function assertNotImplemented(condition, message) {
      if (!condition) {
        Debug.error('NotImplemented: ' + message);
      }
    }
    Debug.assertNotImplemented = assertNotImplemented;
    function warning(message) {
      true;
    }
    Debug.warning = warning;
    function notUsed(message) {
      true;
    }
    Debug.notUsed = notUsed;
    function notImplemented(message) {
      true;
    }
    Debug.notImplemented = notImplemented;
    function somewhatImplemented(message) {
      Debug.warning('somewhatImplemented: ' + message);
    }
    Debug.somewhatImplemented = somewhatImplemented;
    function unexpected(message) {
      Debug.assert(false, 'Unexpected: ' + message);
    }
    Debug.unexpected = unexpected;
  }(Shumway.Debug || (Shumway.Debug = {})));
  var Debug = Shumway.Debug;
  function getTicks() {
    return performance.now();
  }
  Shumway.getTicks = getTicks;
  (function (ArrayUtilities) {
    function popManyInto(src, count, dst) {
      true;
      for (var i = count - 1; i >= 0; i--) {
        dst[i] = src.pop();
      }
      dst.length = count;
    }
    ArrayUtilities.popManyInto = popManyInto;
  }(Shumway.ArrayUtilities || (Shumway.ArrayUtilities = {})));
  var ArrayUtilities = Shumway.ArrayUtilities;
  (function (ObjectUtilities) {
    function boxValue(value) {
      if (Shumway.isNullOrUndefined(value) || Shumway.isObject(value)) {
        return value;
      }
      return Object(value);
    }
    ObjectUtilities.boxValue = boxValue;
    function toKeyValueArray(object) {
      var hasOwnProperty = Object.prototype.hasOwnProperty;
      var array = [];
      for (var k in object) {
        if (hasOwnProperty.call(object, k)) {
          array.push([
            k,
            object[k]
          ]);
        }
      }
      return array;
    }
    ObjectUtilities.toKeyValueArray = toKeyValueArray;
    function hasOwnProperty(object, name) {
      return Object.prototype.hasOwnProperty.call(object, name);
    }
    ObjectUtilities.hasOwnProperty = hasOwnProperty;
    function createEmptyObject() {
      return Object.create(null);
    }
    ObjectUtilities.createEmptyObject = createEmptyObject;
    function createMap() {
      return Object.create(null);
    }
    ObjectUtilities.createMap = createMap;
    function createArrayMap() {
      return [];
    }
    ObjectUtilities.createArrayMap = createArrayMap;
    function defineReadOnlyProperty(object, name, value) {
      Object.defineProperty(object, name, {
        value: value,
        writable: false,
        configurable: true,
        enumerable: false
      });
    }
    ObjectUtilities.defineReadOnlyProperty = defineReadOnlyProperty;
    function getOwnPropertyDescriptors(object) {
      var o = ObjectUtilities.createMap();
      var properties = Object.getOwnPropertyNames(object);
      for (var i = 0; i < properties.length; i++) {
        o[properties[i]] = Object.getOwnPropertyDescriptor(object, properties[i]);
      }
      return o;
    }
    ObjectUtilities.getOwnPropertyDescriptors = getOwnPropertyDescriptors;
    function cloneObject(object) {
      var clone = ObjectUtilities.createEmptyObject();
      for (var property in object) {
        clone[property] = object[property];
      }
      return clone;
    }
    ObjectUtilities.cloneObject = cloneObject;
    function copyProperties(object, template) {
      for (var property in template) {
        object[property] = template[property];
      }
    }
    ObjectUtilities.copyProperties = copyProperties;
    function getLatestGetterOrSetterPropertyDescriptor(object, name) {
      var descriptor = {};
      while (object) {
        var tmp = Object.getOwnPropertyDescriptor(object, name);
        if (tmp) {
          descriptor.get = descriptor.get || tmp.get;
          descriptor.set = descriptor.set || tmp.set;
        }
        if (descriptor.get && descriptor.set) {
          break;
        }
        object = Object.getPrototypeOf(object);
      }
      return descriptor;
    }
    ObjectUtilities.getLatestGetterOrSetterPropertyDescriptor = getLatestGetterOrSetterPropertyDescriptor;
    function defineNonEnumerableGetterOrSetter(obj, name, value, isGetter) {
      var descriptor = ObjectUtilities.getLatestGetterOrSetterPropertyDescriptor(obj, name);
      descriptor.configurable = true;
      descriptor.enumerable = false;
      if (isGetter) {
        descriptor.get = value;
      } else {
        descriptor.set = value;
      }
      Object.defineProperty(obj, name, descriptor);
    }
    ObjectUtilities.defineNonEnumerableGetterOrSetter = defineNonEnumerableGetterOrSetter;
    function defineNonEnumerableGetter(obj, name, getter) {
      Object.defineProperty(obj, name, {
        get: getter,
        configurable: true,
        enumerable: false
      });
    }
    ObjectUtilities.defineNonEnumerableGetter = defineNonEnumerableGetter;
    function defineNonEnumerableSetter(obj, name, setter) {
      Object.defineProperty(obj, name, {
        set: setter,
        configurable: true,
        enumerable: false
      });
    }
    ObjectUtilities.defineNonEnumerableSetter = defineNonEnumerableSetter;
    function defineNonEnumerableProperty(obj, name, value) {
      Object.defineProperty(obj, name, {
        value: value,
        writable: true,
        configurable: true,
        enumerable: false
      });
    }
    ObjectUtilities.defineNonEnumerableProperty = defineNonEnumerableProperty;
    function defineNonEnumerableForwardingProperty(obj, name, otherName) {
      Object.defineProperty(obj, name, {
        get: FunctionUtilities.makeForwardingGetter(otherName),
        set: FunctionUtilities.makeForwardingSetter(otherName),
        writable: true,
        configurable: true,
        enumerable: false
      });
    }
    ObjectUtilities.defineNonEnumerableForwardingProperty = defineNonEnumerableForwardingProperty;
    function defineNewNonEnumerableProperty(obj, name, value) {
      true;
      ObjectUtilities.defineNonEnumerableProperty(obj, name, value);
    }
    ObjectUtilities.defineNewNonEnumerableProperty = defineNewNonEnumerableProperty;
  }(Shumway.ObjectUtilities || (Shumway.ObjectUtilities = {})));
  var ObjectUtilities = Shumway.ObjectUtilities;
  (function (FunctionUtilities) {
    function makeForwardingGetter(target) {
      return new Function('return this["' + target + '"]');
    }
    FunctionUtilities.makeForwardingGetter = makeForwardingGetter;
    function makeForwardingSetter(target) {
      return new Function('value', 'this["' + target + '"] = value;');
    }
    FunctionUtilities.makeForwardingSetter = makeForwardingSetter;
    function bindSafely(fn, object) {
      true;
      var f = fn.bind(object);
      f.boundTo = object;
      return f;
    }
    FunctionUtilities.bindSafely = bindSafely;
  }(Shumway.FunctionUtilities || (Shumway.FunctionUtilities = {})));
  var FunctionUtilities = Shumway.FunctionUtilities;
  (function (StringUtilities) {
    function toSafeString(value) {
      if (typeof value === 'string') {
        return '"' + value + '"';
      }
      if (typeof value === 'number' || typeof value === 'boolean') {
        return String(value);
      }
      return typeof value;
    }
    StringUtilities.toSafeString = toSafeString;
    function toSafeArrayString(array) {
      var str = [];
      for (var i = 0; i < array.length; i++) {
        str.push(toSafeString(array[i]));
      }
      return str.join(', ');
    }
    StringUtilities.toSafeArrayString = toSafeArrayString;
    function utf8decode(str) {
      var bytes = new Uint8Array(str.length * 4);
      var b = 0;
      for (var i = 0, j = str.length; i < j; i++) {
        var code = str.charCodeAt(i);
        if (code <= 127) {
          bytes[b++] = code;
          continue;
        }
        if (55296 <= code && code <= 56319) {
          var codeLow = str.charCodeAt(i + 1);
          if (56320 <= codeLow && codeLow <= 57343) {
            code = ((code & 1023) << 10) + (codeLow & 1023) + 65536;
            ++i;
          }
        }
        if ((code & 4292870144) !== 0) {
          bytes[b++] = 248 | code >>> 24 & 3;
          bytes[b++] = 128 | code >>> 18 & 63;
          bytes[b++] = 128 | code >>> 12 & 63;
          bytes[b++] = 128 | code >>> 6 & 63;
          bytes[b++] = 128 | code & 63;
        } else if ((code & 4294901760) !== 0) {
          bytes[b++] = 240 | code >>> 18 & 7;
          bytes[b++] = 128 | code >>> 12 & 63;
          bytes[b++] = 128 | code >>> 6 & 63;
          bytes[b++] = 128 | code & 63;
        } else if ((code & 4294965248) !== 0) {
          bytes[b++] = 224 | code >>> 12 & 15;
          bytes[b++] = 128 | code >>> 6 & 63;
          bytes[b++] = 128 | code & 63;
        } else {
          bytes[b++] = 192 | code >>> 6 & 31;
          bytes[b++] = 128 | code & 63;
        }
      }
      return bytes.subarray(0, b);
    }
    StringUtilities.utf8decode = utf8decode;
    function utf8encode(bytes) {
      var j = 0, str = '';
      while (j < bytes.length) {
        var b1 = bytes[j++] & 255;
        if (b1 <= 127) {
          str += String.fromCharCode(b1);
        } else {
          var currentPrefix = 192;
          var validBits = 5;
          do {
            var mask = currentPrefix >> 1 | 128;
            if ((b1 & mask) === currentPrefix)
              break;
            currentPrefix = currentPrefix >> 1 | 128;
            --validBits;
          } while (validBits >= 0);
          if (validBits <= 0) {
            str += String.fromCharCode(b1);
            continue;
          }
          var code = b1 & (1 << validBits) - 1;
          var invalid = false;
          for (var i = 5; i >= validBits; --i) {
            var bi = bytes[j++];
            if ((bi & 192) != 128) {
              invalid = true;
              break;
            }
            code = code << 6 | bi & 63;
          }
          if (invalid) {
            for (var k = j - (7 - i); k < j; ++k) {
              str += String.fromCharCode(bytes[k] & 255);
            }
            continue;
          }
          if (code >= 65536) {
            str += String.fromCharCode(code - 65536 >> 10 & 1023 | 55296, code & 1023 | 56320);
          } else {
            str += String.fromCharCode(code);
          }
        }
      }
      return str;
    }
    StringUtilities.utf8encode = utf8encode;
    function base64ArrayBuffer(arrayBuffer) {
      var base64 = '';
      var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
      var bytes = new Uint8Array(arrayBuffer);
      var byteLength = bytes.byteLength;
      var byteRemainder = byteLength % 3;
      var mainLength = byteLength - byteRemainder;
      var a, b, c, d;
      var chunk;
      for (var i = 0; i < mainLength; i = i + 3) {
        chunk = bytes[i] << 16 | bytes[i + 1] << 8 | bytes[i + 2];
        a = (chunk & 16515072) >> 18;
        b = (chunk & 258048) >> 12;
        c = (chunk & 4032) >> 6;
        d = chunk & 63;
        base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d];
      }
      if (byteRemainder == 1) {
        chunk = bytes[mainLength];
        a = (chunk & 252) >> 2;
        b = (chunk & 3) << 4;
        base64 += encodings[a] + encodings[b] + '==';
      } else if (byteRemainder == 2) {
        chunk = bytes[mainLength] << 8 | bytes[mainLength + 1];
        a = (chunk & 64512) >> 10;
        b = (chunk & 1008) >> 4;
        c = (chunk & 15) << 2;
        base64 += encodings[a] + encodings[b] + encodings[c] + '=';
      }
      return base64;
    }
    StringUtilities.base64ArrayBuffer = base64ArrayBuffer;
    function escapeString(str) {
      if (str !== undefined) {
        str = str.replace(/[^\w$]/gi, '$');
        if (/^\d/.test(str)) {
          str = '$' + str;
        }
      }
      return str;
    }
    StringUtilities.escapeString = escapeString;
    function fromCharCodeArray(buffer) {
      var str = '', SLICE = 1024 * 16;
      for (var i = 0; i < buffer.length; i += SLICE) {
        var chunk = Math.min(buffer.length - i, SLICE);
        str += String.fromCharCode.apply(null, buffer.subarray(i, i + chunk));
      }
      return str;
    }
    StringUtilities.fromCharCodeArray = fromCharCodeArray;
    var _encoding = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789$_';
    function variableLengthEncodeInt32(n) {
      var e = _encoding;
      var bitCount = 32 - IntegerUtilities.leadingZeros(n);
      var l = Math.ceil(bitCount / 6);
      var s = e[l];
      for (var i = l - 1; i >= 0; i--) {
        var offset = i * 6;
        s += e[n >> offset & 63];
      }
      true;
      return s;
    }
    StringUtilities.variableLengthEncodeInt32 = variableLengthEncodeInt32;
    function toEncoding(n) {
      return _encoding[n];
    }
    StringUtilities.toEncoding = toEncoding;
    function fromEncoding(s) {
      var c = s.charCodeAt(0);
      var e = 0;
      if (c >= 65 && c <= 90) {
        return c - 65;
      } else if (c >= 97 && c <= 122) {
        return c - 71;
      } else if (c >= 48 && c <= 57) {
        return c + 4;
      } else if (c === 36) {
        return 62;
      } else if (c === 95) {
        return 63;
      }
    }
    StringUtilities.fromEncoding = fromEncoding;
    function variableLengthDecodeInt32(s) {
      var l = StringUtilities.fromEncoding(s[0]);
      var n = 0;
      for (var i = 0; i < l; i++) {
        var offset = (l - i - 1) * 6;
        n |= StringUtilities.fromEncoding(s[1 + i]) << offset;
      }
      return n;
    }
    StringUtilities.variableLengthDecodeInt32 = variableLengthDecodeInt32;
  }(Shumway.StringUtilities || (Shumway.StringUtilities = {})));
  var StringUtilities = Shumway.StringUtilities;
  (function (HashUtilities) {
    var _md5R = new Uint8Array([
        7,
        12,
        17,
        22,
        7,
        12,
        17,
        22,
        7,
        12,
        17,
        22,
        7,
        12,
        17,
        22,
        5,
        9,
        14,
        20,
        5,
        9,
        14,
        20,
        5,
        9,
        14,
        20,
        5,
        9,
        14,
        20,
        4,
        11,
        16,
        23,
        4,
        11,
        16,
        23,
        4,
        11,
        16,
        23,
        4,
        11,
        16,
        23,
        6,
        10,
        15,
        21,
        6,
        10,
        15,
        21,
        6,
        10,
        15,
        21,
        6,
        10,
        15,
        21
      ]);
    var _md5K = new Int32Array([
        -680876936,
        -389564586,
        606105819,
        -1044525330,
        -176418897,
        1200080426,
        -1473231341,
        -45705983,
        1770035416,
        -1958414417,
        -42063,
        -1990404162,
        1804603682,
        -40341101,
        -1502002290,
        1236535329,
        -165796510,
        -1069501632,
        643717713,
        -373897302,
        -701558691,
        38016083,
        -660478335,
        -405537848,
        568446438,
        -1019803690,
        -187363961,
        1163531501,
        -1444681467,
        -51403784,
        1735328473,
        -1926607734,
        -378558,
        -2022574463,
        1839030562,
        -35309556,
        -1530992060,
        1272893353,
        -155497632,
        -1094730640,
        681279174,
        -358537222,
        -722521979,
        76029189,
        -640364487,
        -421815835,
        530742520,
        -995338651,
        -198630844,
        1126891415,
        -1416354905,
        -57434055,
        1700485571,
        -1894986606,
        -1051523,
        -2054922799,
        1873313359,
        -30611744,
        -1560198380,
        1309151649,
        -145523070,
        -1120210379,
        718787259,
        -343485551
      ]);
    function hashBytesTo32BitsMD5(data, offset, length) {
      var r = _md5R;
      var k = _md5K;
      var h0 = 1732584193, h1 = -271733879, h2 = -1732584194, h3 = 271733878;
      var paddedLength = length + 72 & ~63;
      var padded = new Uint8Array(paddedLength);
      var i, j, n;
      for (i = 0; i < length; ++i) {
        padded[i] = data[offset++];
      }
      padded[i++] = 128;
      n = paddedLength - 8;
      while (i < n) {
        padded[i++] = 0;
      }
      padded[i++] = length << 3 & 255;
      padded[i++] = length >> 5 & 255;
      padded[i++] = length >> 13 & 255;
      padded[i++] = length >> 21 & 255;
      padded[i++] = length >>> 29 & 255;
      padded[i++] = 0;
      padded[i++] = 0;
      padded[i++] = 0;
      var w = new Int32Array(16);
      for (i = 0; i < paddedLength;) {
        for (j = 0; j < 16; ++j, i += 4) {
          w[j] = padded[i] | padded[i + 1] << 8 | padded[i + 2] << 16 | padded[i + 3] << 24;
        }
        var a = h0, b = h1, c = h2, d = h3, f, g;
        for (j = 0; j < 64; ++j) {
          if (j < 16) {
            f = b & c | ~b & d;
            g = j;
          } else if (j < 32) {
            f = d & b | ~d & c;
            g = 5 * j + 1 & 15;
          } else if (j < 48) {
            f = b ^ c ^ d;
            g = 3 * j + 5 & 15;
          } else {
            f = c ^ (b | ~d);
            g = 7 * j & 15;
          }
          var tmp = d, rotateArg = a + f + k[j] + w[g] | 0, rotate = r[j];
          d = c;
          c = b;
          b = b + (rotateArg << rotate | rotateArg >>> 32 - rotate) | 0;
          a = tmp;
        }
        h0 = h0 + a | 0;
        h1 = h1 + b | 0;
        h2 = h2 + c | 0;
        h3 = h3 + d | 0;
      }
      return h0;
    }
    HashUtilities.hashBytesTo32BitsMD5 = hashBytesTo32BitsMD5;
    function hashBytesTo32BitsAdler(data, offset, length) {
      var a = 1;
      var b = 0;
      var end = offset + length;
      for (var i = offset; i < end; ++i) {
        a = (a + (data[i] & 255)) % 65521;
        b = (b + a) % 65521;
      }
      return b << 16 | a;
    }
    HashUtilities.hashBytesTo32BitsAdler = hashBytesTo32BitsAdler;
  }(Shumway.HashUtilities || (Shumway.HashUtilities = {})));
  var HashUtilities = Shumway.HashUtilities;
  (function (IntegerUtilities) {
    function bitCount(i) {
      i = i - (i >> 1 & 1431655765);
      i = (i & 858993459) + (i >> 2 & 858993459);
      return (i + (i >> 4) & 252645135) * 16843009 >> 24;
    }
    IntegerUtilities.bitCount = bitCount;
    function ones(i) {
      i = i - (i >> 1 & 1431655765);
      i = (i & 858993459) + (i >> 2 & 858993459);
      return (i + (i >> 4) & 252645135) * 16843009 >> 24;
    }
    IntegerUtilities.ones = ones;
    function leadingZeros(i) {
      i |= i >> 1;
      i |= i >> 2;
      i |= i >> 4;
      i |= i >> 8;
      i |= i >> 16;
      return 32 - IntegerUtilities.ones(i);
    }
    IntegerUtilities.leadingZeros = leadingZeros;
    function trailingZeros(i) {
      return IntegerUtilities.ones((i & -i) - 1);
    }
    IntegerUtilities.trailingZeros = trailingZeros;
    function getFlags(i, flags) {
      var str = '';
      for (var i = 0; i < flags.length; i++) {
        if (i & 1 << i) {
          str += flags[i] + ' ';
        }
      }
      if (str.length === 0) {
        return '';
      }
      return str.trim();
    }
    IntegerUtilities.getFlags = getFlags;
    function isPowerOfTwo(x) {
      return x && (x & x - 1) === 0;
    }
    IntegerUtilities.isPowerOfTwo = isPowerOfTwo;
  }(Shumway.IntegerUtilities || (Shumway.IntegerUtilities = {})));
  var IntegerUtilities = Shumway.IntegerUtilities;
  var IndentingWriter = function () {
      function IndentingWriter(suppressOutput, outFn) {
        if (typeof suppressOutput === 'undefined') {
          suppressOutput = false;
        }
        this._tab = '  ';
        this._padding = '';
        this._suppressOutput = suppressOutput;
        this._out = outFn || IndentingWriter._consoleOutFn;
      }
      IndentingWriter.prototype.writeLn = function (str) {
        if (!this._suppressOutput) {
          this._out(this._padding + str);
        }
      };
      IndentingWriter.prototype.writeLns = function (str) {
        var lines = str.split('\n');
        for (var i = 0; i < lines.length; i++) {
          this.writeLn(lines[i]);
        }
      };
      IndentingWriter.prototype.debugLn = function (str) {
        this.colorLn(IndentingWriter.PURPLE, str);
      };
      IndentingWriter.prototype.yellowLn = function (str) {
        this.colorLn(IndentingWriter.YELLOW, str);
      };
      IndentingWriter.prototype.greenLn = function (str) {
        this.colorLn(IndentingWriter.GREEN, str);
      };
      IndentingWriter.prototype.redLn = function (str) {
        this.colorLn(IndentingWriter.RED, str);
      };
      IndentingWriter.prototype.colorLn = function (color, str) {
        if (!this._suppressOutput) {
          if (!inBrowser) {
            this._out(this._padding + color + str + IndentingWriter.ENDC);
          } else {
            this._out(this._padding + str);
          }
        }
      };
      IndentingWriter.prototype.enter = function (str) {
        if (!this._suppressOutput) {
          this._out(this._padding + str);
        }
        this.indent();
      };
      IndentingWriter.prototype.leaveAndEnter = function (str) {
        this.leave(str);
        this.indent();
      };
      IndentingWriter.prototype.leave = function (str) {
        this.outdent();
        if (!this._suppressOutput) {
          this._out(this._padding + str);
        }
      };
      IndentingWriter.prototype.indent = function () {
        this._padding += this._tab;
      };
      IndentingWriter.prototype.outdent = function () {
        if (this._padding.length > 0) {
          this._padding = this._padding.substring(0, this._padding.length - this._tab.length);
        }
      };
      IndentingWriter.prototype.writeArray = function (arr, detailed, noNumbers) {
        if (typeof detailed === 'undefined') {
          detailed = false;
        }
        if (typeof noNumbers === 'undefined') {
          noNumbers = false;
        }
        detailed = detailed || false;
        for (var i = 0, j = arr.length; i < j; i++) {
          var prefix = '';
          if (detailed) {
            if (arr[i] === null) {
              prefix = 'null';
            } else if (arr[i] === undefined) {
              prefix = 'undefined';
            } else {
              prefix = arr[i].constructor.name;
            }
            prefix += ' ';
          }
          var number = noNumbers ? '' : ('' + i).padRight(' ', 4);
          this.writeLn(number + prefix + arr[i]);
        }
      };
      IndentingWriter.PURPLE = '\x1b[94m';
      IndentingWriter.YELLOW = '\x1b[93m';
      IndentingWriter.GREEN = '\x1b[92m';
      IndentingWriter.RED = '\x1b[91m';
      IndentingWriter.ENDC = '\x1b[0m';
      IndentingWriter._consoleOutFn = inBrowser ? console.info.bind(console) : print;
      return IndentingWriter;
    }();
  Shumway.IndentingWriter = IndentingWriter;
  var SortedListNode = function () {
      function SortedListNode(value, next) {
        this.value = value;
        this.next = next;
      }
      return SortedListNode;
    }();
  var SortedList = function () {
      function SortedList(compare) {
        true;
        this._compare = compare;
        this._head = null;
        this._length = 0;
      }
      SortedList.prototype.push = function (value) {
        true;
        this._length++;
        if (!this._head) {
          this._head = new SortedListNode(value, null);
          return;
        }
        var curr = this._head;
        var prev = null;
        var node = new SortedListNode(value, null);
        var compare = this._compare;
        while (curr) {
          if (compare(curr.value, node.value) > 0) {
            if (prev) {
              node.next = curr;
              prev.next = node;
            } else {
              node.next = this._head;
              this._head = node;
            }
            return;
          }
          prev = curr;
          curr = curr.next;
        }
        prev.next = node;
      };
      SortedList.prototype.forEach = function (visitor) {
        var curr = this._head;
        var last = null;
        while (curr) {
          var result = visitor(curr.value);
          if (result === SortedList.RETURN) {
            return;
          } else if (result === SortedList.DELETE) {
            if (!last) {
              curr = this._head = this._head.next;
            } else {
              curr = last.next = curr.next;
            }
          } else {
            last = curr;
            curr = curr.next;
          }
        }
      };
      SortedList.prototype.isEmpty = function () {
        return !this._head;
      };
      SortedList.prototype.pop = function () {
        if (!this._head) {
          return undefined;
        }
        this._length--;
        var ret = this._head;
        this._head = this._head.next;
        return ret.value;
      };
      SortedList.prototype.contains = function (value) {
        var curr = this._head;
        while (curr) {
          if (curr.value === value) {
            return true;
          }
          curr = curr.next;
        }
        return false;
      };
      SortedList.prototype.toString = function () {
        var str = '[';
        var curr = this._head;
        while (curr) {
          str += curr.value.toString();
          curr = curr.next;
          if (curr) {
            str += ',';
          }
        }
        str += ']';
        return str;
      };
      SortedList.RETURN = 1;
      SortedList.DELETE = 2;
      return SortedList;
    }();
  Shumway.SortedList = SortedList;
  var CIRCULAR_BUFFER_MASK = 4095;
  var CIRCULAR_BUFFER_SIZE = 4096;
  var CircularBuffer = function () {
      function CircularBuffer(Type) {
        this.index = 0;
        this.start = 0;
        this.array = new Type(CIRCULAR_BUFFER_SIZE);
      }
      CircularBuffer.prototype.get = function (i) {
        return this.array[i];
      };
      CircularBuffer.prototype.forEachInReverse = function (visitor) {
        if (this.isEmpty()) {
          return;
        }
        var i = this.index === 0 ? CIRCULAR_BUFFER_SIZE - 1 : this.index - 1;
        while (i !== this.start) {
          if (visitor(this.array[i], i)) {
            break;
          }
          i = i === 0 ? CIRCULAR_BUFFER_SIZE - 1 : i - 1;
        }
      };
      CircularBuffer.prototype.write = function (value) {
        this.array[this.index] = value;
        this.index = this.index + 1 & CIRCULAR_BUFFER_MASK;
        if (this.index === this.start) {
          this.start = this.start + 1 & CIRCULAR_BUFFER_MASK;
        }
      };
      CircularBuffer.prototype.isFull = function () {
        return (this.index + 1 & CIRCULAR_BUFFER_MASK) === this.start;
      };
      CircularBuffer.prototype.isEmpty = function () {
        return this.index === this.start;
      };
      return CircularBuffer;
    }();
  Shumway.CircularBuffer = CircularBuffer;
}(Shumway || (Shumway = {})));
var assert = Shumway.Debug.assert;
var IndentingWriter = Shumway.IndentingWriter;
var assert = Shumway.Debug.assert;
var $DEBUG;
var release = true;
var c4CoerceNonPrimitiveParameters = false;
var c4CoerceNonPrimitive = false;
var c4AsTypeLate = true;
var error = Shumway.Debug.error;
var assertNotImplemented = Shumway.Debug.assertNotImplemented;
var warning = Shumway.Debug.warning;
var notImplemented = Shumway.Debug.notImplemented;
var somewhatImplemented = Shumway.Debug.somewhatImplemented;
var unexpected = Shumway.Debug.unexpected;
var defineReadOnlyProperty = Shumway.ObjectUtilities.defineReadOnlyProperty;
var createEmptyObject = Shumway.ObjectUtilities.createEmptyObject;
var makeForwardingGetter = Shumway.FunctionUtilities.makeForwardingGetter;
var makeForwardingSetter = Shumway.FunctionUtilities.makeForwardingSetter;
var bindSafely = Shumway.FunctionUtilities.bindSafely;
var cloneObject = Shumway.ObjectUtilities.cloneObject;
var copyProperties = Shumway.ObjectUtilities.copyProperties;
var toSafeString = Shumway.StringUtilities.toSafeString;
var toSafeArrayString = Shumway.StringUtilities.toSafeArrayString;
var getLatestGetterOrSetterPropertyDescriptor = Shumway.ObjectUtilities.getLatestGetterOrSetterPropertyDescriptor;
var defineNonEnumerableGetterOrSetter = Shumway.ObjectUtilities.defineNonEnumerableGetterOrSetter;
var defineNonEnumerableGetter = Shumway.ObjectUtilities.defineNonEnumerableGetter;
var defineNonEnumerableSetter = Shumway.ObjectUtilities.defineNonEnumerableSetter;
var defineNonEnumerableProperty = Shumway.ObjectUtilities.defineNonEnumerableProperty;
var defineNonEnumerableForwardingProperty = Shumway.ObjectUtilities.defineNonEnumerableForwardingProperty;
var defineNewNonEnumerableProperty = Shumway.ObjectUtilities.defineNewNonEnumerableProperty;
var isNumeric = Shumway.isNumeric;
var isNullOrUndefined = Shumway.isNullOrUndefined;
var isPowerOfTwo = Shumway.IntegerUtilities.isPowerOfTwo;
function time(fn, count) {
  var start = performance.now();
  for (var i = 0; i < count; i++) {
    fn();
  }
  var time = (performance.now() - start) / count;
  console.info('Took: ' + time.toFixed(2) + 'ms.');
  return time;
}
function clamp(x, min, max) {
  if (x < min) {
    return min;
  } else if (x > max) {
    return max;
  }
  return x;
}
var fromCharCodeArray = Shumway.StringUtilities.fromCharCodeArray;
function hasOwnProperty(object, name) {
  return Object.prototype.hasOwnProperty.call(object, name);
}
var toKeyValueArray = Shumway.ObjectUtilities.toKeyValueArray;
var boxValue = Shumway.ObjectUtilities.boxValue;
function isObject(value) {
  return typeof value === 'object' || typeof value === 'function';
}
function isString(value) {
  return typeof value === 'string';
}
function isFunction(value) {
  return typeof value === 'function';
}
function isNumber(value) {
  return typeof value === 'number';
}
function toNumber(x) {
  return +x;
}
function setBitFlags(flags, flag, value) {
  return value ? flags | flag : flags & ~flag;
}
function getBitFlags(flags, flag) {
  return !(!(flags & flag));
}
(function () {
  function extendBuiltin(proto, prop, f) {
    if (!proto[prop]) {
      Object.defineProperty(proto, prop, {
        value: f,
        writable: true,
        configurable: true,
        enumerable: false
      });
    }
  }
  var Sp = String.prototype;
  function removeColors(s) {
    return s.replace(/\033\[[0-9]*m/g, '');
  }
  extendBuiltin(Sp, 'padRight', function (c, n) {
    var str = this;
    var length = removeColors(str).length;
    if (!c || length >= n) {
      return str;
    }
    var max = (n - length) / c.length;
    for (var i = 0; i < max; i++) {
      str += c;
    }
    return str;
  });
  extendBuiltin(Sp, 'padLeft', function (c, n) {
    var str = this;
    var length = str.length;
    if (!c || length >= n) {
      return str;
    }
    var max = (n - length) / c.length;
    for (var i = 0; i < max; i++) {
      str = c + str;
    }
    return str;
  });
  extendBuiltin(Sp, 'trim', function () {
    return this.replace(/^\s+|\s+$/g, '');
  });
  extendBuiltin(Sp, 'endsWith', function (str) {
    return this.indexOf(str, this.length - str.length) !== -1;
  });
  var Ap = Array.prototype;
  extendBuiltin(Ap, 'popMany', function (count) {
    true;
    var start = this.length - count;
    var res = this.slice(start, this.length);
    this.splice(start, count);
    return res;
  });
  extendBuiltin(Ap, 'pushMany', function (array) {
    for (var i = 0; i < array.length; i++) {
      this.push(array[i]);
    }
  });
  extendBuiltin(Ap, 'clone', function () {
    return this.slice(0);
  });
  extendBuiltin(Ap, 'first', function () {
    true;
    return this[0];
  });
  extendBuiltin(Ap, 'last', function () {
    true;
    return this[this.length - 1];
  });
  extendBuiltin(Ap, 'peek', function () {
    true;
    return this[this.length - 1];
  });
  extendBuiltin(Ap, 'empty', function () {
    return this.length === 0;
  });
  extendBuiltin(Ap, 'pushUnique', function (v) {
    for (var i = 0, j = this.length; i < j; i++) {
      if (this[i] === v) {
        return;
      }
    }
    this.push(v);
  });
  var uniquesMap;
  if (typeof Map !== 'undefined' && (uniquesMap = new Map()).clear) {
    extendBuiltin(Ap, 'unique', function () {
      var unique = [];
      for (var i = 0; i < this.length; i++) {
        if (uniquesMap.has(this[i])) {
          continue;
        }
        unique.push(this[i]);
        uniquesMap.set(this[i], true);
      }
      uniquesMap.clear();
      return unique;
    });
  } else {
    extendBuiltin(Ap, 'unique', function () {
      var unique = [];
      for (var i = 0; i < this.length; i++) {
        unique.pushUnique(this[i]);
      }
      return unique;
    });
  }
  extendBuiltin(Ap, 'replace', function (x, y) {
    if (x === y) {
      return 0;
    }
    var count = 0;
    for (var i = 0; i < this.length; i++) {
      if (this[i] === x) {
        this[i] = y;
        count++;
      }
    }
    return count;
  });
  extendBuiltin(Ap, 'count', function (x) {
    var count = 0;
    for (var i = 0; i < this.length; i++) {
      if (this[i] === x) {
        count++;
      }
    }
    return count;
  });
  extendBuiltin(Ap, 'notEmpty', function () {
    return this.length > 0;
  });
  extendBuiltin(Ap, 'contains', function (val) {
    return this.indexOf(val) >= 0;
  });
  extendBuiltin(Ap, 'top', function () {
    return this.length && this[this.length - 1];
  });
  extendBuiltin(Ap, 'mapWithIndex', function (fn) {
    var arr = [];
    for (var i = 0; i < this.length; i++) {
      arr.push(fn(this[i], i));
    }
    return arr;
  });
}());
var utf8decode = Shumway.StringUtilities.utf8decode;
var utf8encode = Shumway.StringUtilities.utf8encode;
var escapeString = Shumway.StringUtilities.escapeString;
var bitCount = Shumway.IntegerUtilities.bitCount;
var ones = Shumway.IntegerUtilities.ones;
var leadingZeros = Shumway.IntegerUtilities.leadingZeros;
var trailingZeros = Shumway.IntegerUtilities.trailingZeros;
var getFlags = Shumway.IntegerUtilities.getFlags;
function BitSetFunctor(length) {
  var ADDRESS_BITS_PER_WORD = 5;
  var BITS_PER_WORD = 1 << ADDRESS_BITS_PER_WORD;
  var BIT_INDEX_MASK = BITS_PER_WORD - 1;
  var SIZE = length + (BITS_PER_WORD - 1) >> ADDRESS_BITS_PER_WORD << ADDRESS_BITS_PER_WORD;
  function BitSet() {
    this.count = 0;
    this.dirty = 0;
    this.size = SIZE;
    this.bits = new Uint32Array(SIZE >> ADDRESS_BITS_PER_WORD);
  }
  function BitSetS() {
    this.count = 0;
    this.dirty = 0;
    this.size = SIZE;
    this.bits = 0;
  }
  var singleword = SIZE >> ADDRESS_BITS_PER_WORD === 1;
  var Ctor = singleword ? BitSetS : BitSet;
  Ctor.ADDRESS_BITS_PER_WORD = ADDRESS_BITS_PER_WORD;
  Ctor.BITS_PER_WORD = BITS_PER_WORD;
  Ctor.BIT_INDEX_MASK = BIT_INDEX_MASK;
  Ctor.singleword = singleword;
  BitSet.prototype = {
    recount: function recount() {
      if (!this.dirty) {
        return;
      }
      var bits = this.bits;
      var c = 0;
      for (var i = 0, j = bits.length; i < j; i++) {
        var v = bits[i];
        v = v - (v >> 1 & 1431655765);
        v = (v & 858993459) + (v >> 2 & 858993459);
        c += (v + (v >> 4) & 252645135) * 16843009 >> 24;
      }
      this.count = c;
      this.dirty = 0;
    },
    set: function set(i) {
      var n = i >> ADDRESS_BITS_PER_WORD;
      var old = this.bits[n];
      var b = old | 1 << (i & BIT_INDEX_MASK);
      this.bits[n] = b;
      this.dirty |= old ^ b;
    },
    setAll: function setAll() {
      var bits = this.bits;
      for (var i = 0, j = bits.length; i < j; i++) {
        bits[i] = 4294967295;
      }
      this.count = this.size;
      this.dirty = 0;
    },
    assign: function assign(set) {
      this.count = set.count;
      this.dirty = set.dirty;
      this.size = set.size;
      for (var i = 0, j = this.bits.length; i < j; i++) {
        this.bits[i] = set.bits[i];
      }
    },
    clear: function clear(i) {
      var n = i >> ADDRESS_BITS_PER_WORD;
      var old = this.bits[n];
      var b = old & ~(1 << (i & BIT_INDEX_MASK));
      this.bits[n] = b;
      this.dirty |= old ^ b;
    },
    get: function get(i) {
      var word = this.bits[i >> ADDRESS_BITS_PER_WORD];
      return (word & 1 << (i & BIT_INDEX_MASK)) !== 0;
    },
    clearAll: function clearAll() {
      var bits = this.bits;
      for (var i = 0, j = bits.length; i < j; i++) {
        bits[i] = 0;
      }
      this.count = 0;
      this.dirty = 0;
    },
    _union: function _union(other) {
      var dirty = this.dirty;
      var bits = this.bits;
      var otherBits = other.bits;
      for (var i = 0, j = bits.length; i < j; i++) {
        var old = bits[i];
        var b = old | otherBits[i];
        bits[i] = b;
        dirty |= old ^ b;
      }
      this.dirty = dirty;
    },
    intersect: function intersect(other) {
      var dirty = this.dirty;
      var bits = this.bits;
      var otherBits = other.bits;
      for (var i = 0, j = bits.length; i < j; i++) {
        var old = bits[i];
        var b = old & otherBits[i];
        bits[i] = b;
        dirty |= old ^ b;
      }
      this.dirty = dirty;
    },
    subtract: function subtract(other) {
      var dirty = this.dirty;
      var bits = this.bits;
      var otherBits = other.bits;
      for (var i = 0, j = bits.length; i < j; i++) {
        var old = bits[i];
        var b = old & ~otherBits[i];
        bits[i] = b;
        dirty |= old ^ b;
      }
      this.dirty = dirty;
    },
    negate: function negate() {
      var dirty = this.dirty;
      var bits = this.bits;
      for (var i = 0, j = bits.length; i < j; i++) {
        var old = bits[i];
        var b = ~old;
        bits[i] = b;
        dirty |= old ^ b;
      }
      this.dirty = dirty;
    },
    forEach: function forEach(fn) {
      true;
      var bits = this.bits;
      for (var i = 0, j = bits.length; i < j; i++) {
        var word = bits[i];
        if (word) {
          for (var k = 0; k < BITS_PER_WORD; k++) {
            if (word & 1 << k) {
              fn(i * BITS_PER_WORD + k);
            }
          }
        }
      }
    },
    toArray: function toArray() {
      var set = [];
      var bits = this.bits;
      for (var i = 0, j = bits.length; i < j; i++) {
        var word = bits[i];
        if (word) {
          for (var k = 0; k < BITS_PER_WORD; k++) {
            if (word & 1 << k) {
              set.push(i * BITS_PER_WORD + k);
            }
          }
        }
      }
      return set;
    },
    equals: function equals(other) {
      if (this.size !== other.size) {
        return false;
      }
      var bits = this.bits;
      var otherBits = other.bits;
      for (var i = 0, j = bits.length; i < j; i++) {
        if (bits[i] !== otherBits[i]) {
          return false;
        }
      }
      return true;
    },
    contains: function contains(other) {
      if (this.size !== other.size) {
        return false;
      }
      var bits = this.bits;
      var otherBits = other.bits;
      for (var i = 0, j = bits.length; i < j; i++) {
        if ((bits[i] | otherBits[i]) !== bits[i]) {
          return false;
        }
      }
      return true;
    },
    toBitString: function toBitString(on, off) {
      on = on || '1';
      off = off || '0';
      var str = '';
      for (var i = 0; i < length; i++) {
        str += this.get(i) ? on : off;
      }
      return str;
    },
    length: length,
    toString: function toString(names) {
      var set = [];
      for (var i = 0; i < length; i++) {
        if (this.get(i)) {
          set.push(names ? names[i] : i);
        }
      }
      return set.join(', ');
    },
    isEmpty: function isEmpty() {
      this.recount();
      return this.count === 0;
    },
    clone: function clone() {
      var set = new BitSet();
      set._union(this);
      return set;
    }
  };
  BitSetS.prototype = {
    recount: function recount() {
      if (!this.dirty) {
        return;
      }
      var c = 0;
      var v = this.bits;
      v = v - (v >> 1 & 1431655765);
      v = (v & 858993459) + (v >> 2 & 858993459);
      c += (v + (v >> 4) & 252645135) * 16843009 >> 24;
      this.count = c;
      this.dirty = 0;
    },
    set: function set(i) {
      var old = this.bits;
      var b = old | 1 << (i & BIT_INDEX_MASK);
      this.bits = b;
      this.dirty |= old ^ b;
    },
    setAll: function setAll() {
      this.bits = 4294967295;
      this.count = this.size;
      this.dirty = 0;
    },
    assign: function assign(set) {
      this.count = set.count;
      this.dirty = set.dirty;
      this.size = set.size;
      this.bits = set.bits;
    },
    clear: function clear(i) {
      var old = this.bits;
      var b = old & ~(1 << (i & BIT_INDEX_MASK));
      this.bits = b;
      this.dirty |= old ^ b;
    },
    get: function get(i) {
      return (this.bits & 1 << (i & BIT_INDEX_MASK)) !== 0;
    },
    clearAll: function clearAll() {
      this.bits = 0;
      this.count = 0;
      this.dirty = 0;
    },
    _union: function _union(other) {
      var old = this.bits;
      var b = old | other.bits;
      this.bits = b;
      this.dirty = old ^ b;
    },
    intersect: function intersect(other) {
      var old = this.bits;
      var b = old & other.bits;
      this.bits = b;
      this.dirty = old ^ b;
    },
    subtract: function subtract(other) {
      var old = this.bits;
      var b = old & ~other.bits;
      this.bits = b;
      this.dirty = old ^ b;
    },
    negate: function negate() {
      var old = this.bits;
      var b = ~old;
      this.bits = b;
      this.dirty = old ^ b;
    },
    forEach: function forEach(fn) {
      true;
      var word = this.bits;
      if (word) {
        for (var k = 0; k < BITS_PER_WORD; k++) {
          if (word & 1 << k) {
            fn(k);
          }
        }
      }
    },
    toArray: function toArray() {
      var set = [];
      var word = this.bits;
      if (word) {
        for (var k = 0; k < BITS_PER_WORD; k++) {
          if (word & 1 << k) {
            set.push(k);
          }
        }
      }
      return set;
    },
    equals: function equals(other) {
      return this.bits === other.bits;
    },
    contains: function contains(other) {
      var bits = this.bits;
      return (bits | other.bits) === bits;
    },
    isEmpty: function isEmpty() {
      this.recount();
      return this.count === 0;
    },
    clone: function clone() {
      var set = new BitSetS();
      set._union(this);
      return set;
    },
    toBitString: BitSet.prototype.toBitString,
    toString: BitSet.prototype.toString,
    length: length
  };
  return Ctor;
}
var Map = function () {
    function map() {
      this.elements = {};
    }
    map.prototype.set = function set(k, v) {
      this.elements[k] = v;
    };
    map.prototype.get = function get(k) {
      if (this.has(k)) {
        return this.elements[k];
      }
      return undefined;
    };
    map.prototype.has = function has(k) {
      return Object.prototype.hasOwnProperty.call(this.elements, k);
    };
    map.prototype.remove = function remove(k) {
      if (this.has(k)) {
        delete this.elements[k];
      }
    };
    return map;
  }();
(function checkWeakMap() {
  if (typeof this.WeakMap === 'function')
    return;
  var id = 0;
  function WeakMap() {
    this.id = '$weakmap' + id++;
  }
  ;
  WeakMap.prototype = {
    has: function (obj) {
      return obj.hasOwnProperty(this.id);
    },
    get: function (obj, defaultValue) {
      return obj.hasOwnProperty(this.id) ? obj[this.id] : defaultValue;
    },
    set: function (obj, value) {
      Object.defineProperty(obj, this.id, {
        value: value,
        enumerable: false,
        configurable: true
      });
    }
  };
  this.WeakMap = WeakMap;
}());
var Callback = function () {
    function callback() {
      this.queues = {};
    }
    callback.prototype.register = function register(type, callback) {
      var queue = this.queues[type];
      if (queue) {
        if (queue.indexOf(callback) > -1) {
          return;
        }
      } else {
        queue = this.queues[type] = [];
      }
      queue.push(callback);
    };
    callback.prototype.unregister = function unregister(type, callback) {
      var queue = this.queues[type];
      if (!queue) {
        return;
      }
      var i = queue.indexOf(callback);
      if (i !== -1) {
        queue.splice(i, 1);
      }
      if (queue.length === 0) {
        this.queues[type] = null;
      }
    };
    callback.prototype.notify = function notify(type, args) {
      var queue = this.queues[type];
      if (!queue) {
        return;
      }
      queue = queue.slice();
      var args = sliceArguments(arguments, 0);
      for (var i = 0; i < queue.length; i++) {
        if (false) {
          Counter.count('callback(' + type + ').notify');
        }
        var callback = queue[i];
        callback.apply(null, args);
      }
    };
    callback.prototype.notify1 = function notify1(type, value) {
      var queue = this.queues[type];
      if (!queue) {
        return;
      }
      queue = queue.slice();
      for (var i = 0; i < queue.length; i++) {
        if (false) {
          Counter.count('callback(' + type + ').notify1');
        }
        var callback = queue[i];
        callback(type, value);
      }
    };
    return callback;
  }();
function lazyClass(holder, name, initialize) {
  Object.defineProperty(holder, name, {
    get: function () {
      var start = performance.now();
      var value = initialize();
      print('Initialized Class: ' + name + ' ' + (performance.now() - start).toFixed(4));
      Object.defineProperty(holder, name, {
        value: value,
        writable: true
      });
      return value;
    },
    configurable: true
  });
}
var hashBytesTo32BitsAdler = Shumway.HashUtilities.hashBytesTo32BitsAdler;
var hashBytesTo32BitsMD5 = Shumway.HashUtilities.hashBytesTo32BitsMD5;
var variableLengthEncodeInt32 = Shumway.StringUtilities.variableLengthEncodeInt32;
var fromEncoding = Shumway.StringUtilities.fromEncoding;
var variableLengthDecodeIdentifier = Shumway.StringUtilities.variableLengthDecodeInt32;
var toEncoding = Shumway.StringUtilities.toEncoding;
var Shumway;
(function (Shumway) {
  (function (Options) {
    var Argument = function () {
        function Argument(shortName, longName, type, options) {
          this.shortName = shortName;
          this.longName = longName;
          this.type = type;
          options = options || {};
          this.positional = options.positional;
          this.parseFn = options.parse;
          this.value = options.defaultValue;
        }
        Argument.prototype.parse = function (value) {
          if (this.type === 'boolean') {
            true;
            this.value = value;
          } else if (this.type === 'number') {
            true;
            this.value = parseInt(value, 10);
          } else {
            this.value = value;
          }
          if (this.parseFn) {
            this.parseFn(this.value);
          }
        };
        return Argument;
      }();
    Options.Argument = Argument;
    var ArgumentParser = function () {
        function ArgumentParser() {
          this.args = [];
        }
        ArgumentParser.prototype.addArgument = function (shortName, longName, type, options) {
          var argument = new Argument(shortName, longName, type, options);
          this.args.push(argument);
          return argument;
        };
        ArgumentParser.prototype.addBoundOption = function (option) {
          var options = {
              parse: function (x) {
                option.value = x;
              }
            };
          this.args.push(new Argument(option.shortName, option.longName, option.type, options));
        };
        ArgumentParser.prototype.addBoundOptionSet = function (optionSet) {
          var self = this;
          optionSet.options.forEach(function (x) {
            if (x instanceof OptionSet) {
              self.addBoundOptionSet(x);
            } else {
              true;
              self.addBoundOption(x);
            }
          });
        };
        ArgumentParser.prototype.getUsage = function () {
          var str = '';
          this.args.forEach(function (x) {
            if (!x.positional) {
              str += '[-' + x.shortName + '|--' + x.longName + (x.type === 'boolean' ? '' : ' ' + x.type[0].toUpperCase()) + ']';
            } else {
              str += x.longName;
            }
            str += ' ';
          });
          return str;
        };
        ArgumentParser.prototype.parse = function (args) {
          var nonPositionalArgumentMap = {};
          var positionalArgumentList = [];
          this.args.forEach(function (x) {
            if (x.positional) {
              positionalArgumentList.push(x);
            } else {
              nonPositionalArgumentMap['-' + x.shortName] = x;
              nonPositionalArgumentMap['--' + x.longName] = x;
            }
          });
          var leftoverArguments = [];
          while (args.length) {
            var argString = args.shift();
            var argument = null, value = argString;
            if (argString == '--') {
              leftoverArguments = leftoverArguments.concat(args);
              break;
            } else if (argString.slice(0, 1) == '-' || argString.slice(0, 2) == '--') {
              argument = nonPositionalArgumentMap[argString];
              true;
              if (!argument) {
                continue;
              }
              if (argument.type !== 'boolean') {
                value = args.shift();
                true;
              } else {
                value = true;
              }
            } else if (positionalArgumentList.length) {
              argument = positionalArgumentList.shift();
            } else {
              leftoverArguments.push(value);
            }
            if (argument) {
              argument.parse(value);
            }
          }
          true;
          return leftoverArguments;
        };
        return ArgumentParser;
      }();
    Options.ArgumentParser = ArgumentParser;
    var OptionSet = function () {
        function OptionSet(name) {
          this.name = name;
          this.options = [];
        }
        OptionSet.prototype.register = function (option) {
          this.options.push(option);
          return option;
        };
        OptionSet.prototype.trace = function (writer) {
          writer.enter(this.name + ' {');
          this.options.forEach(function (option) {
            option.trace(writer);
          });
          writer.leave('}');
        };
        return OptionSet;
      }();
    Options.OptionSet = OptionSet;
    var Option = function () {
        function Option(shortName, longName, type, defaultValue, description) {
          this.longName = longName;
          this.shortName = shortName;
          this.type = type;
          this.defaultValue = defaultValue;
          this.value = defaultValue;
          this.description = description;
        }
        Option.prototype.parse = function (value) {
          this.value = value;
        };
        Option.prototype.trace = function (writer) {
          writer.writeLn(('-' + this.shortName + '|--' + this.longName).padRight(' ', 30) + ' = ' + this.type + ' ' + this.value + ' [' + this.defaultValue + ']' + ' (' + this.description + ')');
        };
        return Option;
      }();
    Options.Option = Option;
  }(Shumway.Options || (Shumway.Options = {})));
  var Options = Shumway.Options;
}(Shumway || (Shumway = {})));
if (typeof exports !== 'undefined') {
  exports['Shumway'] = Shumway;
}
var ArgumentParser = Shumway.Options.ArgumentParser;
var Option = Shumway.Options.Option;
var OptionSet = Shumway.Options.OptionSet;
var ArgumentParser = Shumway.Options.ArgumentParser;
var Option = Shumway.Options.Option;
var OptionSet = Shumway.Options.OptionSet;
var Shumway;
(function (Shumway) {
  (function (Metrics) {
    var Timer = function () {
        function Timer(parent, name) {
          this._parent = parent;
          this._timers = Shumway.ObjectUtilities.createMap();
          this._name = name;
          this._begin = 0;
          this._last = 0;
          this._total = 0;
          this._count = 0;
        }
        Timer.time = function (name, fn) {
          Timer.start(name);
          fn();
          Timer.stop();
        };
        Timer.start = function (name) {
          Timer._top = Timer._top._timers[name] || (Timer._top._timers[name] = new Timer(Timer._top, name));
          Timer._top.start();
          var tmp = Timer._flat._timers[name] || (Timer._flat._timers[name] = new Timer(Timer._flat, name));
          tmp.start();
          Timer._flatStack.push(tmp);
        };
        Timer.stop = function () {
          Timer._top.stop();
          Timer._top = Timer._top._parent;
          Timer._flatStack.pop().stop();
        };
        Timer.stopStart = function (name) {
          Timer.stop();
          Timer.start(name);
        };
        Timer.prototype.start = function () {
          this._begin = Shumway.getTicks();
        };
        Timer.prototype.stop = function () {
          this._last = Shumway.getTicks() - this._begin;
          this._total += this._last;
          this._count += 1;
        };
        Timer.prototype.toJSON = function () {
          return {
            name: this._name,
            total: this._total,
            timers: this._timers
          };
        };
        Timer.prototype.trace = function (writer) {
          writer.enter(this._name + ': ' + this._total.toFixed(2) + ' ms' + ', count: ' + this._count + ', average: ' + (this._total / this._count).toFixed(2) + ' ms');
          for (var name in this._timers) {
            this._timers[name].trace(writer);
          }
          writer.outdent();
        };
        Timer.trace = function (writer) {
          Timer._base.trace(writer);
          Timer._flat.trace(writer);
        };
        Timer._base = new Timer(null, 'Total');
        Timer._top = Timer._base;
        Timer._flat = new Timer(null, 'Flat');
        Timer._flatStack = [];
        return Timer;
      }();
    Metrics.Timer = Timer;
    var Counter = function () {
        function Counter(enabled) {
          this._enabled = enabled;
          this.clear();
        }
        Counter.prototype.setEnabled = function (enabled) {
          this._enabled = enabled;
        };
        Counter.prototype.clear = function () {
          this._counts = Shumway.ObjectUtilities.createMap();
        };
        Counter.prototype.toJSON = function () {
          return {
            counts: this._counts
          };
        };
        Counter.prototype.count = function (name, increment) {
          if (typeof increment === 'undefined') {
            increment = 1;
          }
          if (!this._enabled) {
            return;
          }
          if (this._counts[name] === undefined) {
            this._counts[name] = 0;
          }
          this._counts[name] += increment;
          return this._counts[name];
        };
        Counter.prototype.trace = function (writer) {
          for (var name in this._counts) {
            writer.writeLn(name + ': ' + this._counts[name]);
          }
        };
        Counter.prototype.traceSorted = function (writer) {
          var pairs = [];
          for (var name in this._counts) {
            pairs.push([
              name,
              this._counts[name]
            ]);
          }
          pairs.sort(function (a, b) {
            return b[1] - a[1];
          });
          pairs.forEach(function (pair) {
            writer.writeLn(pair[0] + ': ' + pair[1]);
          });
        };
        return Counter;
      }();
    Metrics.Counter = Counter;
    var Average = function () {
        function Average(max) {
          this._samples = new Float64Array(max);
          this._count = 0;
          this._index = 0;
        }
        Average.prototype.push = function (sample) {
          if (this._count < this._samples.length) {
            this._count++;
          }
          this._index++;
          this._samples[this._index % this._samples.length] = sample;
        };
        Average.prototype.average = function () {
          var sum = 0;
          for (var i = 0; i < this._count; i++) {
            sum += this._samples[i];
          }
          return sum / this._count;
        };
        return Average;
      }();
    Metrics.Average = Average;
  }(Shumway.Metrics || (Shumway.Metrics = {})));
  var Metrics = Shumway.Metrics;
}(Shumway || (Shumway = {})));
var Timer = Shumway.Metrics.Timer;
var Counter = new Shumway.Metrics.Counter(true);
var Timer = Shumway.Metrics.Timer;
var Counter = new Shumway.Metrics.Counter(true);
var FrameCounter = new Shumway.Metrics.Counter(true);
var systemOptions = new OptionSet('System Options');
var disassemble = systemOptions.register(new Option('d', 'disassemble', 'boolean', false, 'disassemble'));
var traceLevel = systemOptions.register(new Option('t', 'traceLevel', 'number', 0, 'trace level'));
window.print = function (s) {
  console.log(s);
};
var CONSTANT_Undefined = 0;
var CONSTANT_Utf8 = 1;
var CONSTANT_Float = 2;
var CONSTANT_Int = 3;
var CONSTANT_UInt = 4;
var CONSTANT_PrivateNs = 5;
var CONSTANT_Double = 6;
var CONSTANT_QName = 7;
var CONSTANT_Namespace = 8;
var CONSTANT_Multiname = 9;
var CONSTANT_False = 10;
var CONSTANT_True = 11;
var CONSTANT_Null = 12;
var CONSTANT_QNameA = 13;
var CONSTANT_MultinameA = 14;
var CONSTANT_RTQName = 15;
var CONSTANT_RTQNameA = 16;
var CONSTANT_RTQNameL = 17;
var CONSTANT_RTQNameLA = 18;
var CONSTANT_NameL = 19;
var CONSTANT_NameLA = 20;
var CONSTANT_NamespaceSet = 21;
var CONSTANT_PackageNamespace = 22;
var CONSTANT_PackageInternalNs = 23;
var CONSTANT_ProtectedNamespace = 24;
var CONSTANT_ExplicitNamespace = 25;
var CONSTANT_StaticProtectedNs = 26;
var CONSTANT_MultinameL = 27;
var CONSTANT_MultinameLA = 28;
var CONSTANT_TypeName = 29;
var CONSTANT_ClassSealed = 1;
var CONSTANT_ClassFinal = 2;
var CONSTANT_ClassInterface = 4;
var CONSTANT_ClassProtectedNs = 8;
var TRAIT_Slot = 0;
var TRAIT_Method = 1;
var TRAIT_Getter = 2;
var TRAIT_Setter = 3;
var TRAIT_Class = 4;
var TRAIT_Function = 5;
var TRAIT_Const = 6;
var ATTR_Final = 1;
var ATTR_Override = 2;
var ATTR_Metadata = 4;
var SLOT_var = 0;
var SLOT_method = 1;
var SLOT_getter = 2;
var SLOT_setter = 3;
var SLOT_class = 4;
var SLOT_function = 6;
var METHOD_Arguments = 1;
var METHOD_Activation = 2;
var METHOD_Needrest = 4;
var METHOD_HasOptional = 8;
var METHOD_IgnoreRest = 16;
var METHOD_Native = 32;
var METHOD_Setsdxns = 64;
var METHOD_HasParamNames = 128;
var OP_bkpt = 1;
var OP_nop = 2;
var OP_throw = 3;
var OP_getsuper = 4;
var OP_setsuper = 5;
var OP_dxns = 6;
var OP_dxnslate = 7;
var OP_kill = 8;
var OP_label = 9;
var OP_lf32x4 = 10;
var OP_sf32x4 = 11;
var OP_ifnlt = 12;
var OP_ifnle = 13;
var OP_ifngt = 14;
var OP_ifnge = 15;
var OP_jump = 16;
var OP_iftrue = 17;
var OP_iffalse = 18;
var OP_ifeq = 19;
var OP_ifne = 20;
var OP_iflt = 21;
var OP_ifle = 22;
var OP_ifgt = 23;
var OP_ifge = 24;
var OP_ifstricteq = 25;
var OP_ifstrictne = 26;
var OP_lookupswitch = 27;
var OP_pushwith = 28;
var OP_popscope = 29;
var OP_nextname = 30;
var OP_hasnext = 31;
var OP_pushnull = 32;
var OP_pushundefined = 33;
var OP_pushfloat = 34;
var OP_nextvalue = 35;
var OP_pushbyte = 36;
var OP_pushshort = 37;
var OP_pushtrue = 38;
var OP_pushfalse = 39;
var OP_pushnan = 40;
var OP_pop = 41;
var OP_dup = 42;
var OP_swap = 43;
var OP_pushstring = 44;
var OP_pushint = 45;
var OP_pushuint = 46;
var OP_pushdouble = 47;
var OP_pushscope = 48;
var OP_pushnamespace = 49;
var OP_hasnext2 = 50;
var OP_li8 = 53;
var OP_li16 = 54;
var OP_li32 = 55;
var OP_lf32 = 56;
var OP_lf64 = 57;
var OP_si8 = 58;
var OP_si16 = 59;
var OP_si32 = 60;
var OP_sf32 = 61;
var OP_sf64 = 62;
var OP_newfunction = 64;
var OP_call = 65;
var OP_construct = 66;
var OP_callmethod = 67;
var OP_callstatic = 68;
var OP_callsuper = 69;
var OP_callproperty = 70;
var OP_returnvoid = 71;
var OP_returnvalue = 72;
var OP_constructsuper = 73;
var OP_constructprop = 74;
var OP_callsuperid = 75;
var OP_callproplex = 76;
var OP_callinterface = 77;
var OP_callsupervoid = 78;
var OP_callpropvoid = 79;
var OP_sxi1 = 80;
var OP_sxi8 = 81;
var OP_sxi16 = 82;
var OP_applytype = 83;
var OP_pushfloat4 = 84;
var OP_newobject = 85;
var OP_newarray = 86;
var OP_newactivation = 87;
var OP_newclass = 88;
var OP_getdescendants = 89;
var OP_newcatch = 90;
var OP_findpropstrict = 93;
var OP_findproperty = 94;
var OP_finddef = 95;
var OP_getlex = 96;
var OP_setproperty = 97;
var OP_getlocal = 98;
var OP_setlocal = 99;
var OP_getglobalscope = 100;
var OP_getscopeobject = 101;
var OP_getproperty = 102;
var OP_getouterscope = 103;
var OP_initproperty = 104;
var OP_setpropertylate = 105;
var OP_deleteproperty = 106;
var OP_deletepropertylate = 107;
var OP_getslot = 108;
var OP_setslot = 109;
var OP_getglobalslot = 110;
var OP_setglobalslot = 111;
var OP_convert_s = 112;
var OP_esc_xelem = 113;
var OP_esc_xattr = 114;
var OP_convert_i = 115;
var OP_convert_u = 116;
var OP_convert_d = 117;
var OP_convert_b = 118;
var OP_convert_o = 119;
var OP_checkfilter = 120;
var OP_convert_f = 121;
var OP_unplus = 122;
var OP_convert_f4 = 123;
var OP_coerce = 128;
var OP_coerce_b = 129;
var OP_coerce_a = 130;
var OP_coerce_i = 131;
var OP_coerce_d = 132;
var OP_coerce_s = 133;
var OP_astype = 134;
var OP_astypelate = 135;
var OP_coerce_u = 136;
var OP_coerce_o = 137;
var OP_negate = 144;
var OP_increment = 145;
var OP_inclocal = 146;
var OP_decrement = 147;
var OP_declocal = 148;
var OP_typeof = 149;
var OP_not = 150;
var OP_bitnot = 151;
var OP_add = 160;
var OP_subtract = 161;
var OP_multiply = 162;
var OP_divide = 163;
var OP_modulo = 164;
var OP_lshift = 165;
var OP_rshift = 166;
var OP_urshift = 167;
var OP_bitand = 168;
var OP_bitor = 169;
var OP_bitxor = 170;
var OP_equals = 171;
var OP_strictequals = 172;
var OP_lessthan = 173;
var OP_lessequals = 174;
var OP_greaterthan = 175;
var OP_greaterequals = 176;
var OP_instanceof = 177;
var OP_istype = 178;
var OP_istypelate = 179;
var OP_in = 180;
var OP_increment_i = 192;
var OP_decrement_i = 193;
var OP_inclocal_i = 194;
var OP_declocal_i = 195;
var OP_negate_i = 196;
var OP_add_i = 197;
var OP_subtract_i = 198;
var OP_multiply_i = 199;
var OP_getlocal0 = 208;
var OP_getlocal1 = 209;
var OP_getlocal2 = 210;
var OP_getlocal3 = 211;
var OP_setlocal0 = 212;
var OP_setlocal1 = 213;
var OP_setlocal2 = 214;
var OP_setlocal3 = 215;
var OP_invalid = 237;
var OP_debug = 239;
var OP_debugline = 240;
var OP_debugfile = 241;
var OP_bkptline = 242;
var OP_timestamp = 243;
var INT_MIN_VALUE = -2147483648;
var INT_MAX_VALUE = 2147483647;
var UINT_MIN_VALUE = 0;
var UINT_MAX_VALUE = 4294967295;
var SORT_CASEINSENSITIVE = 1;
var SORT_DESCENDING = 2;
var SORT_UNIQUESORT = 4;
var SORT_RETURNINDEXEDARRAY = 8;
var SORT_NUMERIC = 16;
var Shumway;
(function (Shumway) {
  (function (AVM2) {
    AVM2.Errors = {
      CallOfNonFunctionError: {
        code: 1006,
        message: '%1 is not a function.'
      },
      ConvertNullToObjectError: {
        code: 1009,
        message: 'Cannot access a property or method of a null object reference.'
      },
      ConvertUndefinedToObjectError: {
        code: 1010,
        message: 'A term is undefined and has no properties.'
      },
      ClassNotFoundError: {
        code: 1014,
        message: 'Class %1 could not be found.'
      },
      CheckTypeFailedError: {
        code: 1034,
        message: 'Type Coercion failed: cannot convert %1 to %2.'
      },
      WrongArgumentCountError: {
        code: 1063,
        message: 'Argument count mismatch on %1. Expected %2, got %3.'
      },
      XMLMarkupMustBeWellFormed: {
        code: 1088,
        message: 'The markup in the document following the root element must be well-formed.'
      },
      OutOfRangeError: {
        code: 1125,
        message: 'The index %1 is out of range %2.'
      },
      VectorFixedError: {
        code: 1126,
        message: 'Cannot change the length of a fixed Vector.'
      },
      InvalidParamError: {
        code: 2004,
        message: 'One of the parameters is invalid.'
      },
      ParamRangeError: {
        code: 2006,
        message: 'The supplied index is out of bounds.'
      },
      NullPointerError: {
        code: 2007,
        message: 'Parameter %1 must be non-null.'
      },
      InvalidEnumError: {
        code: 2008,
        message: 'Parameter %1 must be one of the accepted values.'
      },
      ArgumentError: {
        code: 2015,
        message: 'Invalid BitmapData.'
      },
      CompressedDataError: {
        code: 2058,
        message: 'There was an error decompressing the data.'
      },
      SocketConnectError: {
        code: 2011,
        message: 'Socket connection failed to %1:%2.'
      },
      CantAddSelfError: {
        code: 2024,
        message: 'An object cannot be added as a child of itself.'
      },
      NotAChildError: {
        code: 2025,
        message: 'The supplied DisplayObject must be a child of the caller.'
      },
      ExternalInterfaceNotAvailableError: {
        code: 2067,
        message: 'The ExternalInterface is not available in this container. ExternalInterface requires Internet Explorer ActiveX, Firefox, Mozilla 1.7.5 and greater, or other browsers that support NPRuntime.'
      }
    };
    function getErrorMessage(index) {
      if (!Shumway.AVM2.Runtime.debuggerMode.value) {
        return 'Error #' + index;
      }
      for (var k in AVM2.Errors) {
        if (AVM2.Errors[k].code == index) {
          return 'Error #' + index + ': ' + AVM2.Errors[k].message;
        }
      }
      return 'Error #' + index + ': (unknown)';
    }
    AVM2.getErrorMessage = getErrorMessage;
    function formatErrorMessage(error) {
      var args = [];
      for (var _i = 0; _i < arguments.length - 1; _i++) {
        args[_i] = arguments[_i + 1];
      }
      var message = error.message;
      Array.prototype.slice.call(arguments, 1).forEach(function (x, i) {
        message = message.replace('%' + (i + 1), x);
      });
      return 'Error #' + error.code + ': ' + message;
    }
    AVM2.formatErrorMessage = formatErrorMessage;
    function translateErrorMessage(error) {
      if (error.type) {
        switch (error.type) {
        case 'undefined_method':
          return formatErrorMessage(AVM2.Errors.CallOfNonFunctionError, 'value');
        default:
          throw Shumway.Debug.notImplemented(error.type);
        }
      } else {
        if (error.message.indexOf('is not a function') >= 0) {
          return formatErrorMessage(AVM2.Errors.CallOfNonFunctionError, 'value');
        }
        return error.message;
      }
    }
    AVM2.translateErrorMessage = translateErrorMessage;
  }(Shumway.AVM2 || (Shumway.AVM2 = {})));
  var AVM2 = Shumway.AVM2;
}(Shumway || (Shumway = {})));
var Errors = Shumway.AVM2.Errors;
var getErrorMessage = Shumway.AVM2.getErrorMessage;
var formatErrorMessage = Shumway.AVM2.formatErrorMessage;
var translateErrorMessage = Shumway.AVM2.translateErrorMessage;
var Errors = Shumway.AVM2.Errors;
var getErrorMessage = Shumway.AVM2.getErrorMessage;
var formatErrorMessage = Shumway.AVM2.formatErrorMessage;
var translateErrorMessage = Shumway.AVM2.translateErrorMessage;
var Shumway;
(function (Shumway) {
  (function (AVM2) {
    AVM2.opcodeTable = [
      null,
      {
        name: 'bkpt',
        canThrow: false,
        operands: []
      },
      {
        name: 'nop',
        canThrow: false,
        operands: []
      },
      {
        name: 'throw',
        canThrow: true,
        operands: []
      },
      {
        name: 'getsuper',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'setsuper',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'dxns',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'dxnslate',
        canThrow: true,
        operands: []
      },
      {
        name: 'kill',
        canThrow: false,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'label',
        canThrow: false,
        operands: []
      },
      {
        name: 'lf32x4',
        canThrow: true,
        operands: []
      },
      {
        name: 'sf32x4',
        canThrow: true,
        operands: []
      },
      {
        name: 'ifnlt',
        canThrow: true,
        operands: [
          {
            name: 'offset',
            size: 's24',
            type: ''
          }
        ]
      },
      {
        name: 'ifnle',
        canThrow: true,
        operands: [
          {
            name: 'offset',
            size: 's24',
            type: ''
          }
        ]
      },
      {
        name: 'ifngt',
        canThrow: true,
        operands: [
          {
            name: 'offset',
            size: 's24',
            type: ''
          }
        ]
      },
      {
        name: 'ifnge',
        canThrow: true,
        operands: [
          {
            name: 'offset',
            size: 's24',
            type: ''
          }
        ]
      },
      {
        name: 'jump',
        canThrow: false,
        operands: [
          {
            name: 'offset',
            size: 's24',
            type: ''
          }
        ]
      },
      {
        name: 'iftrue',
        canThrow: false,
        operands: [
          {
            name: 'offset',
            size: 's24',
            type: ''
          }
        ]
      },
      {
        name: 'iffalse',
        canThrow: false,
        operands: [
          {
            name: 'offset',
            size: 's24',
            type: ''
          }
        ]
      },
      {
        name: 'ifeq',
        canThrow: true,
        operands: [
          {
            name: 'offset',
            size: 's24',
            type: ''
          }
        ]
      },
      {
        name: 'ifne',
        canThrow: true,
        operands: [
          {
            name: 'offset',
            size: 's24',
            type: ''
          }
        ]
      },
      {
        name: 'iflt',
        canThrow: true,
        operands: [
          {
            name: 'offset',
            size: 's24',
            type: ''
          }
        ]
      },
      {
        name: 'ifle',
        canThrow: true,
        operands: [
          {
            name: 'offset',
            size: 's24',
            type: ''
          }
        ]
      },
      {
        name: 'ifgt',
        canThrow: true,
        operands: [
          {
            name: 'offset',
            size: 's24',
            type: ''
          }
        ]
      },
      {
        name: 'ifge',
        canThrow: true,
        operands: [
          {
            name: 'offset',
            size: 's24',
            type: ''
          }
        ]
      },
      {
        name: 'ifstricteq',
        canThrow: false,
        operands: [
          {
            name: 'offset',
            size: 's24',
            type: ''
          }
        ]
      },
      {
        name: 'ifstrictne',
        canThrow: false,
        operands: [
          {
            name: 'offset',
            size: 's24',
            type: ''
          }
        ]
      },
      {
        name: 'lookupswitch',
        canThrow: false,
        operands: null
      },
      {
        name: 'pushwith',
        canThrow: false,
        operands: []
      },
      {
        name: 'popscope',
        canThrow: false,
        operands: []
      },
      {
        name: 'nextname',
        canThrow: true,
        operands: []
      },
      {
        name: 'hasnext',
        canThrow: true,
        operands: []
      },
      {
        name: 'pushnull',
        canThrow: false,
        operands: []
      },
      {
        name: 'pushundefined',
        canThrow: false,
        operands: []
      },
      null,
      {
        name: 'nextvalue',
        canThrow: true,
        operands: []
      },
      {
        name: 'pushbyte',
        canThrow: false,
        operands: [
          {
            name: 'value',
            size: 's08',
            type: ''
          }
        ]
      },
      {
        name: 'pushshort',
        canThrow: false,
        operands: [
          {
            name: 'value',
            size: 's16',
            type: ''
          }
        ]
      },
      {
        name: 'pushtrue',
        canThrow: false,
        operands: []
      },
      {
        name: 'pushfalse',
        canThrow: false,
        operands: []
      },
      {
        name: 'pushnan',
        canThrow: false,
        operands: []
      },
      {
        name: 'pop',
        canThrow: false,
        operands: []
      },
      {
        name: 'dup',
        canThrow: false,
        operands: []
      },
      {
        name: 'swap',
        canThrow: false,
        operands: []
      },
      {
        name: 'pushstring',
        canThrow: false,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'S'
          }
        ]
      },
      {
        name: 'pushint',
        canThrow: false,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'I'
          }
        ]
      },
      {
        name: 'pushuint',
        canThrow: false,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'U'
          }
        ]
      },
      {
        name: 'pushdouble',
        canThrow: false,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'D'
          }
        ]
      },
      {
        name: 'pushscope',
        canThrow: false,
        operands: []
      },
      {
        name: 'pushnamespace',
        canThrow: false,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'N'
          }
        ]
      },
      {
        name: 'hasnext2',
        canThrow: true,
        operands: [
          {
            name: 'object',
            size: 'u30',
            type: ''
          },
          {
            name: 'index',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'lix8',
        canThrow: true,
        operands: null
      },
      {
        name: 'lix16',
        canThrow: true,
        operands: null
      },
      {
        name: 'li8',
        canThrow: true,
        operands: []
      },
      {
        name: 'li16',
        canThrow: true,
        operands: []
      },
      {
        name: 'li32',
        canThrow: true,
        operands: []
      },
      {
        name: 'lf32',
        canThrow: true,
        operands: []
      },
      {
        name: 'lf64',
        canThrow: true,
        operands: []
      },
      {
        name: 'si8',
        canThrow: true,
        operands: []
      },
      {
        name: 'si16',
        canThrow: true,
        operands: []
      },
      {
        name: 'si32',
        canThrow: true,
        operands: []
      },
      {
        name: 'sf32',
        canThrow: true,
        operands: []
      },
      {
        name: 'sf64',
        canThrow: true,
        operands: []
      },
      null,
      {
        name: 'newfunction',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'MI'
          }
        ]
      },
      {
        name: 'call',
        canThrow: true,
        operands: [
          {
            name: 'argCount',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'construct',
        canThrow: true,
        operands: [
          {
            name: 'argCount',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'callmethod',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: ''
          },
          {
            name: 'argCount',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'callstatic',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'MI'
          },
          {
            name: 'argCount',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'callsuper',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'M'
          },
          {
            name: 'argCount',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'callproperty',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'M'
          },
          {
            name: 'argCount',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'returnvoid',
        canThrow: false,
        operands: []
      },
      {
        name: 'returnvalue',
        canThrow: true,
        operands: []
      },
      {
        name: 'constructsuper',
        canThrow: true,
        operands: [
          {
            name: 'argCount',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'constructprop',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'M'
          },
          {
            name: 'argCount',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'callsuperid',
        canThrow: true,
        operands: null
      },
      {
        name: 'callproplex',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'M'
          },
          {
            name: 'argCount',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'callinterface',
        canThrow: true,
        operands: null
      },
      {
        name: 'callsupervoid',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'M'
          },
          {
            name: 'argCount',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'callpropvoid',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'M'
          },
          {
            name: 'argCount',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'sxi1',
        canThrow: false,
        operands: []
      },
      {
        name: 'sxi8',
        canThrow: false,
        operands: []
      },
      {
        name: 'sxi16',
        canThrow: false,
        operands: []
      },
      {
        name: 'applytype',
        canThrow: true,
        operands: [
          {
            name: 'argCount',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'pushfloat4',
        canThrow: false,
        operands: null
      },
      {
        name: 'newobject',
        canThrow: true,
        operands: [
          {
            name: 'argCount',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'newarray',
        canThrow: true,
        operands: [
          {
            name: 'argCount',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'newactivation',
        canThrow: true,
        operands: []
      },
      {
        name: 'newclass',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'CI'
          }
        ]
      },
      {
        name: 'getdescendants',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'M'
          }
        ]
      },
      {
        name: 'newcatch',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'EI'
          }
        ]
      },
      {
        name: 'findpropglobalstrict',
        canThrow: true,
        operands: null
      },
      {
        name: 'findpropglobal',
        canThrow: true,
        operands: null
      },
      {
        name: 'findpropstrict',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'M'
          }
        ]
      },
      {
        name: 'findproperty',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'M'
          }
        ]
      },
      {
        name: 'finddef',
        canThrow: true,
        operands: null
      },
      {
        name: 'getlex',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'M'
          }
        ]
      },
      {
        name: 'setproperty',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'M'
          }
        ]
      },
      {
        name: 'getlocal',
        canThrow: false,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'setlocal',
        canThrow: false,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'getglobalscope',
        canThrow: false,
        operands: []
      },
      {
        name: 'getscopeobject',
        canThrow: false,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'getproperty',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'M'
          }
        ]
      },
      {
        name: 'getouterscope',
        canThrow: false,
        operands: null
      },
      {
        name: 'initproperty',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'M'
          }
        ]
      },
      null,
      {
        name: 'deleteproperty',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'M'
          }
        ]
      },
      null,
      {
        name: 'getslot',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'setslot',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'getglobalslot',
        canThrow: false,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'setglobalslot',
        canThrow: false,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'convert_s',
        canThrow: true,
        operands: []
      },
      {
        name: 'esc_xelem',
        canThrow: true,
        operands: []
      },
      {
        name: 'esc_xattr',
        canThrow: true,
        operands: []
      },
      {
        name: 'convert_i',
        canThrow: true,
        operands: []
      },
      {
        name: 'convert_u',
        canThrow: true,
        operands: []
      },
      {
        name: 'convert_d',
        canThrow: true,
        operands: []
      },
      {
        name: 'convert_b',
        canThrow: true,
        operands: []
      },
      {
        name: 'convert_o',
        canThrow: true,
        operands: []
      },
      {
        name: 'checkfilter',
        canThrow: true,
        operands: []
      },
      {
        name: 'convert_f',
        canThrow: true,
        operands: []
      },
      {
        name: 'unplus',
        canThrow: true,
        operands: []
      },
      {
        name: 'convert_f4',
        canThrow: true,
        operands: []
      },
      null,
      null,
      null,
      null,
      {
        name: 'coerce',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'M'
          }
        ]
      },
      {
        name: 'coerce_b',
        canThrow: true,
        operands: []
      },
      {
        name: 'coerce_a',
        canThrow: true,
        operands: []
      },
      {
        name: 'coerce_i',
        canThrow: true,
        operands: []
      },
      {
        name: 'coerce_d',
        canThrow: true,
        operands: []
      },
      {
        name: 'coerce_s',
        canThrow: true,
        operands: []
      },
      {
        name: 'astype',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'M'
          }
        ]
      },
      {
        name: 'astypelate',
        canThrow: true,
        operands: []
      },
      {
        name: 'coerce_u',
        canThrow: true,
        operands: []
      },
      {
        name: 'coerce_o',
        canThrow: true,
        operands: []
      },
      null,
      null,
      null,
      null,
      null,
      null,
      {
        name: 'negate',
        canThrow: true,
        operands: []
      },
      {
        name: 'increment',
        canThrow: true,
        operands: []
      },
      {
        name: 'inclocal',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'decrement',
        canThrow: true,
        operands: []
      },
      {
        name: 'declocal',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'typeof',
        canThrow: false,
        operands: []
      },
      {
        name: 'not',
        canThrow: false,
        operands: []
      },
      {
        name: 'bitnot',
        canThrow: true,
        operands: []
      },
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      {
        name: 'add',
        canThrow: true,
        operands: []
      },
      {
        name: 'subtract',
        canThrow: true,
        operands: []
      },
      {
        name: 'multiply',
        canThrow: true,
        operands: []
      },
      {
        name: 'divide',
        canThrow: true,
        operands: []
      },
      {
        name: 'modulo',
        canThrow: true,
        operands: []
      },
      {
        name: 'lshift',
        canThrow: true,
        operands: []
      },
      {
        name: 'rshift',
        canThrow: true,
        operands: []
      },
      {
        name: 'urshift',
        canThrow: true,
        operands: []
      },
      {
        name: 'bitand',
        canThrow: true,
        operands: []
      },
      {
        name: 'bitor',
        canThrow: true,
        operands: []
      },
      {
        name: 'bitxor',
        canThrow: true,
        operands: []
      },
      {
        name: 'equals',
        canThrow: true,
        operands: []
      },
      {
        name: 'strictequals',
        canThrow: true,
        operands: []
      },
      {
        name: 'lessthan',
        canThrow: true,
        operands: []
      },
      {
        name: 'lessequals',
        canThrow: true,
        operands: []
      },
      {
        name: 'greaterthan',
        canThrow: true,
        operands: []
      },
      {
        name: 'greaterequals',
        canThrow: true,
        operands: []
      },
      {
        name: 'instanceof',
        canThrow: true,
        operands: []
      },
      {
        name: 'istype',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'M'
          }
        ]
      },
      {
        name: 'istypelate',
        canThrow: true,
        operands: []
      },
      {
        name: 'in',
        canThrow: true,
        operands: []
      },
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      {
        name: 'increment_i',
        canThrow: true,
        operands: []
      },
      {
        name: 'decrement_i',
        canThrow: true,
        operands: []
      },
      {
        name: 'inclocal_i',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'declocal_i',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'negate_i',
        canThrow: true,
        operands: []
      },
      {
        name: 'add_i',
        canThrow: true,
        operands: []
      },
      {
        name: 'subtract_i',
        canThrow: true,
        operands: []
      },
      {
        name: 'multiply_i',
        canThrow: true,
        operands: []
      },
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      {
        name: 'getlocal0',
        canThrow: false,
        operands: []
      },
      {
        name: 'getlocal1',
        canThrow: false,
        operands: []
      },
      {
        name: 'getlocal2',
        canThrow: false,
        operands: []
      },
      {
        name: 'getlocal3',
        canThrow: false,
        operands: []
      },
      {
        name: 'setlocal0',
        canThrow: false,
        operands: []
      },
      {
        name: 'setlocal1',
        canThrow: false,
        operands: []
      },
      {
        name: 'setlocal2',
        canThrow: false,
        operands: []
      },
      {
        name: 'setlocal3',
        canThrow: false,
        operands: []
      },
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      {
        name: 'invalid',
        canThrow: false,
        operands: []
      },
      null,
      {
        name: 'debug',
        canThrow: true,
        operands: [
          {
            name: 'debugType',
            size: 'u08',
            type: ''
          },
          {
            name: 'index',
            size: 'u30',
            type: 'S'
          },
          {
            name: 'reg',
            size: 'u08',
            type: ''
          },
          {
            name: 'extra',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'debugline',
        canThrow: true,
        operands: [
          {
            name: 'lineNumber',
            size: 'u30',
            type: ''
          }
        ]
      },
      {
        name: 'debugfile',
        canThrow: true,
        operands: [
          {
            name: 'index',
            size: 'u30',
            type: 'S'
          }
        ]
      },
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null
    ];
    function opcodeName(op) {
      return AVM2.opcodeTable[op].name;
    }
    AVM2.opcodeName = opcodeName;
  }(Shumway.AVM2 || (Shumway.AVM2 = {})));
  var AVM2 = Shumway.AVM2;
}(Shumway || (Shumway = {})));
var opcodeTable = Shumway.AVM2.opcodeTable;
var opcodeName = Shumway.AVM2.opcodeName;
var opcodeTable = Shumway.AVM2.opcodeTable;
var opcodeName = Shumway.AVM2.opcodeName;
var __extends = this.__extends || function (d, b) {
    for (var p in b)
      if (b.hasOwnProperty(p))
        d[p] = b[p];
    function __() {
      this.constructor = d;
    }
    __.prototype = b.prototype;
    d.prototype = new __();
  };
var Shumway;
(function (Shumway) {
  (function (AVM2) {
    (function (ABC) {
      var Timer = Shumway.Metrics.Timer;
      var isString = Shumway.isString;
      var isNumber = Shumway.isNumber;
      var isNumeric = Shumway.isNumeric;
      var isObject = Shumway.isObject;
      var textDecoder = null;
      if (typeof TextDecoder !== 'undefined') {
        textDecoder = new TextDecoder();
      }
      var AbcStream = function () {
          function AbcStream(bytes) {
            this._bytes = bytes;
            this._view = new DataView(bytes.buffer, bytes.byteOffset);
            this._position = 0;
          }
          AbcStream._getResultBuffer = function (length) {
            if (!AbcStream._resultBuffer || AbcStream._resultBuffer.length < length) {
              AbcStream._resultBuffer = new Int32Array(length * 2);
            }
            return AbcStream._resultBuffer;
          };
          Object.defineProperty(AbcStream.prototype, 'position', {
            get: function () {
              return this._position;
            },
            enumerable: true,
            configurable: true
          });
          AbcStream.prototype.remaining = function () {
            return this._bytes.length - this._position;
          };
          AbcStream.prototype.seek = function (position) {
            this._position = position;
          };
          AbcStream.prototype.readU8 = function () {
            return this._bytes[this._position++];
          };
          AbcStream.prototype.readU8s = function (count) {
            var b = new Uint8Array(count);
            b.set(this._bytes.subarray(this._position, this._position + count), 0);
            this._position += count;
            return b;
          };
          AbcStream.prototype.readS8 = function () {
            return this._bytes[this._position++] << 24 >> 24;
          };
          AbcStream.prototype.readU32 = function () {
            return this.readS32() >>> 0;
          };
          AbcStream.prototype.readU30 = function () {
            var result = this.readU32();
            if (result & 3221225472) {
              return result;
            }
            return result;
          };
          AbcStream.prototype.readU30Unsafe = function () {
            return this.readU32();
          };
          AbcStream.prototype.readS16 = function () {
            return this.readU30Unsafe() << 16 >> 16;
          };
          AbcStream.prototype.readS32 = function () {
            var result = this.readU8();
            if (result & 128) {
              result = result & 127 | this.readU8() << 7;
              if (result & 16384) {
                result = result & 16383 | this.readU8() << 14;
                if (result & 2097152) {
                  result = result & 2097151 | this.readU8() << 21;
                  if (result & 268435456) {
                    result = result & 268435455 | this.readU8() << 28;
                    result = result & 4294967295;
                  }
                }
              }
            }
            return result;
          };
          AbcStream.prototype.readWord = function () {
            var result = this._view.getUint32(this._position, true);
            this._position += 4;
            return result;
          };
          AbcStream.prototype.readS24 = function () {
            var u = this.readU8() | this.readU8() << 8 | this.readU8() << 16;
            return u << 8 >> 8;
          };
          AbcStream.prototype.readDouble = function () {
            var result = this._view.getFloat64(this._position, true);
            this._position += 8;
            return result;
          };
          AbcStream.prototype.readUTFString = function (length) {
            if (textDecoder) {
              var position = this._position;
              this._position += length;
              return textDecoder.decode(this._bytes.subarray(position, position + length));
            }
            var pos = this._position;
            var end = pos + length;
            var bytes = this._bytes;
            var i = 0;
            var result = AbcStream._getResultBuffer(length * 2);
            while (pos < end) {
              var c = bytes[pos++];
              if (c <= 127) {
                result[i++] = c;
              } else if (c >= 192) {
                var code = 0;
                if (c < 224) {
                  code = (c & 31) << 6 | bytes[pos++] & 63;
                } else if (c < 240) {
                  code = (c & 15) << 12 | (bytes[pos++] & 63) << 6 | bytes[pos++] & 63;
                } else {
                  code = ((c & 7) << 18 | (bytes[pos++] & 63) << 12 | (bytes[pos++] & 63) << 6 | bytes[pos++] & 63) - 65536;
                  result[i++] = ((code & 1047552) >>> 10) + 55296;
                  code = (code & 1023) + 56320;
                }
                result[i++] = code;
              }
            }
            this._position = pos;
            return Shumway.StringUtilities.fromCharCodeArray(result.subarray(0, i));
          };
          AbcStream._resultBuffer = new Int32Array(256);
          return AbcStream;
        }();
      ABC.AbcStream = AbcStream;
      var Parameter = function () {
          function Parameter(name, type, value) {
            this.name = name;
            this.type = type;
            this.value = value;
          }
          return Parameter;
        }();
      ABC.Parameter = Parameter;
      var Trait = function () {
          function Trait(abc, stream, holder) {
            var constantPool = abc.constantPool;
            var methods = abc.methods;
            var classes = abc.classes;
            var metadata = abc.metadata;
            this.holder = holder;
            this.name = constantPool.multinames[stream.readU30()];
            var tag = stream.readU8();
            this.kind = tag & 15;
            this.attributes = tag >> 4 & 15;
            true;
            switch (this.kind) {
            case 0:
            case 6:
              this.slotId = stream.readU30();
              this.typeName = constantPool.multinames[stream.readU30()];
              var valueIndex = stream.readU30();
              this.value = undefined;
              if (valueIndex !== 0) {
                this.hasDefaultValue = true;
                this.value = constantPool.getValue(stream.readU8(), valueIndex);
              }
              break;
            case 1:
            case 3:
            case 2:
              this.dispId = stream.readU30();
              this.methodInfo = methods[stream.readU30()];
              this.methodInfo.name = this.name;
              AbcFile.attachHolder(this.methodInfo, this.holder);
              this.methodInfo.abc = abc;
              break;
            case 4:
              this.slotId = stream.readU30();
              true;
              this.classInfo = classes[stream.readU30()];
              break;
            case 5:
              true;
              break;
            }
            if (this.attributes & 4) {
              var traitMetadata;
              for (var i = 0, j = stream.readU30(); i < j; i++) {
                var md = metadata[stream.readU30()];
                if (md.name === '__go_to_definition_help' || md.name === '__go_to_ctor_definition_help') {
                  continue;
                }
                if (!traitMetadata) {
                  traitMetadata = {};
                }
                traitMetadata[md.name] = md;
              }
              if (traitMetadata) {
                if (this.isClass()) {
                  this.classInfo.metadata = traitMetadata;
                }
                this.metadata = traitMetadata;
              }
            }
          }
          Trait.prototype.isSlot = function () {
            return this.kind === 0;
          };
          Trait.prototype.isConst = function () {
            return this.kind === 6;
          };
          Trait.prototype.isMethod = function () {
            return this.kind === 1;
          };
          Trait.prototype.isClass = function () {
            return this.kind === 4;
          };
          Trait.prototype.isGetter = function () {
            return this.kind === 2;
          };
          Trait.prototype.isSetter = function () {
            return this.kind === 3;
          };
          Trait.prototype.isProtected = function () {
            true;
            return this.name.namespaces[0].isProtected();
          };
          Trait.prototype.kindName = function () {
            switch (this.kind) {
            case 0:
              return 'Slot';
            case 6:
              return 'Const';
            case 1:
              return 'Method';
            case 3:
              return 'Setter';
            case 2:
              return 'Getter';
            case 4:
              return 'Class';
            case 5:
              return 'Function';
            }
            Shumway.Debug.unexpected();
          };
          Trait.prototype.isOverride = function () {
            return this.attributes & 2;
          };
          Trait.prototype.isFinal = function () {
            return this.attributes & 1;
          };
          Trait.prototype.toString = function () {
            var str = Shumway.IntegerUtilities.getFlags(this.attributes, 'final|override|metadata'.split('|'));
            if (str) {
              str += ' ';
            }
            str += Multiname.getQualifiedName(this.name);
            switch (this.kind) {
            case 0:
            case 6:
              return str + ', typeName: ' + this.typeName + ', slotId: ' + this.slotId + ', value: ' + this.value;
            case 1:
            case 3:
            case 2:
              return str + ', ' + this.kindName() + ': ' + this.methodInfo.name;
            case 4:
              return str + ', slotId: ' + this.slotId + ', class: ' + this.classInfo;
            case 5:
              break;
            }
          };
          Trait.parseTraits = function (abc, stream, holder) {
            var count = stream.readU30();
            var traits = [];
            for (var i = 0; i < count; i++) {
              traits.push(new Trait(abc, stream, holder));
            }
            return traits;
          };
          return Trait;
        }();
      ABC.Trait = Trait;
      var Info = function () {
          function Info(abc, index) {
            this.abc = abc;
            this.index = index;
          }
          return Info;
        }();
      ABC.Info = Info;
      var MethodInfo = function (_super) {
          __extends(MethodInfo, _super);
          function MethodInfo(abc, index, stream) {
            _super.call(this, abc, index);
            var constantPool = abc.constantPool;
            var parameterCount = stream.readU30();
            this.returnType = constantPool.multinames[stream.readU30()];
            this.parameters = [];
            for (var i = 0; i < parameterCount; i++) {
              this.parameters.push(new Parameter(undefined, constantPool.multinames[stream.readU30()], undefined));
            }
            this.debugName = constantPool.strings[stream.readU30()];
            this.flags = stream.readU8();
            var optionalCount = 0;
            if (this.flags & 8) {
              optionalCount = stream.readU30();
              true;
              for (var i = parameterCount - optionalCount; i < parameterCount; i++) {
                var valueIndex = stream.readU30();
                this.parameters[i].value = constantPool.getValue(stream.readU8(), valueIndex);
              }
            }
            if (this.flags & 128) {
              for (var i = 0; i < parameterCount; i++) {
                if (false) {
                  this.parameters[i].name = constantPool.strings[stream.readU30()];
                } else {
                  stream.readU30();
                  this.parameters[i].name = MethodInfo._getParameterName(i);
                }
              }
            } else {
              for (var i = 0; i < parameterCount; i++) {
                this.parameters[i].name = MethodInfo._getParameterName(i);
              }
            }
          }
          MethodInfo._getParameterName = function (i) {
            true;
            return String.fromCharCode('A'.charCodeAt(0) + i);
          };
          MethodInfo.prototype.toString = function () {
            var flags = Shumway.IntegerUtilities.getFlags(this.flags, 'NEED_ARGUMENTS|NEED_ACTIVATION|NEED_REST|HAS_OPTIONAL|||SET_DXN|HAS_PARAM_NAMES'.split('|'));
            return (flags ? flags + ' ' : '') + this.name;
          };
          MethodInfo.prototype.hasOptional = function () {
            return !(!(this.flags & 8));
          };
          MethodInfo.prototype.needsActivation = function () {
            return !(!(this.flags & 2));
          };
          MethodInfo.prototype.needsRest = function () {
            return !(!(this.flags & 4));
          };
          MethodInfo.prototype.needsArguments = function () {
            return !(!(this.flags & 1));
          };
          MethodInfo.prototype.isNative = function () {
            return !(!(this.flags & 32));
          };
          MethodInfo.prototype.isClassMember = function () {
            return this.holder instanceof ClassInfo;
          };
          MethodInfo.prototype.isInstanceMember = function () {
            return this.holder instanceof InstanceInfo;
          };
          MethodInfo.prototype.isScriptMember = function () {
            return this.holder instanceof ScriptInfo;
          };
          MethodInfo.parseException = function (abc, stream) {
            var multinames = abc.constantPool.multinames;
            var ex = {
                start: stream.readU30(),
                end: stream.readU30(),
                target: stream.readU30(),
                typeName: multinames[stream.readU30()],
                varName: multinames[stream.readU30()]
              };
            true;
            true;
            return ex;
          };
          MethodInfo.parseBody = function (abc, stream) {
            var constantPool = abc.constantPool;
            var methods = abc.methods;
            var index = stream.readU30();
            var mi = methods[index];
            mi.index = index;
            mi.hasBody = true;
            mi.hash = abc.hash + 196608 + index;
            true;
            mi.maxStack = stream.readU30();
            mi.localCount = stream.readU30();
            mi.initScopeDepth = stream.readU30();
            mi.maxScopeDepth = stream.readU30();
            mi.code = stream.readU8s(stream.readU30());
            var exceptions = [];
            var exceptionCount = stream.readU30();
            for (var i = 0; i < exceptionCount; ++i) {
              exceptions.push(MethodInfo.parseException(abc, stream));
            }
            mi.exceptions = exceptions;
            mi.traits = Trait.parseTraits(abc, stream, mi);
          };
          MethodInfo.prototype.hasExceptions = function () {
            return this.exceptions.length > 0;
          };
          return MethodInfo;
        }(Info);
      ABC.MethodInfo = MethodInfo;
      var InstanceInfo = function (_super) {
          __extends(InstanceInfo, _super);
          function InstanceInfo(abc, index, stream) {
            _super.call(this, abc, index);
            this.runtimeId = InstanceInfo.nextID++;
            var constantPool = abc.constantPool;
            var methods = abc.methods;
            this.name = constantPool.multinames[stream.readU30()];
            true;
            this.superName = constantPool.multinames[stream.readU30()];
            this.flags = stream.readU8();
            this.protectedNs = undefined;
            if (this.flags & 8) {
              this.protectedNs = constantPool.namespaces[stream.readU30()];
            }
            var interfaceCount = stream.readU30();
            this.interfaces = [];
            for (var i = 0; i < interfaceCount; i++) {
              this.interfaces[i] = constantPool.multinames[stream.readU30()];
            }
            this.init = methods[stream.readU30()];
            this.init.isInstanceInitializer = true;
            this.init.name = this.name;
            AbcFile.attachHolder(this.init, this);
            this.traits = Trait.parseTraits(abc, stream, this);
          }
          InstanceInfo.prototype.toString = function () {
            var flags = Shumway.IntegerUtilities.getFlags(this.flags & 8, 'sealed|final|interface|protected'.split('|'));
            var str = (flags ? flags + ' ' : '') + this.name;
            if (this.superName) {
              str += ' extends ' + this.superName;
            }
            return str;
          };
          InstanceInfo.prototype.isFinal = function () {
            return !(!(this.flags & 2));
          };
          InstanceInfo.prototype.isSealed = function () {
            return !(!(this.flags & 1));
          };
          InstanceInfo.prototype.isInterface = function () {
            return !(!(this.flags & 4));
          };
          InstanceInfo.nextID = 1;
          return InstanceInfo;
        }(Info);
      ABC.InstanceInfo = InstanceInfo;
      var ClassInfo = function (_super) {
          __extends(ClassInfo, _super);
          function ClassInfo(abc, index, stream) {
            _super.call(this, abc, index);
            this.runtimeId = ClassInfo.nextID++;
            this.abc = abc;
            this.hash = abc.hash + 65536 + index;
            this.index = index;
            this.init = abc.methods[stream.readU30()];
            this.init.isClassInitializer = true;
            AbcFile.attachHolder(this.init, this);
            this.traits = Trait.parseTraits(abc, stream, this);
            this.instanceInfo = abc.instances[index];
            this.instanceInfo.classInfo = this;
            this.defaultValue = ClassInfo._getDefaultValue(this.instanceInfo.name);
          }
          ClassInfo._getDefaultValue = function (qn) {
            if (Multiname.getQualifiedName(qn) === Multiname.Int || Multiname.getQualifiedName(qn) === Multiname.Uint) {
              return 0;
            } else if (Multiname.getQualifiedName(qn) === Multiname.Number) {
              return NaN;
            } else if (Multiname.getQualifiedName(qn) === Multiname.Boolean) {
              return false;
            } else {
              return null;
            }
          };
          ClassInfo.prototype.toString = function () {
            return this.instanceInfo.name.toString();
          };
          ClassInfo.nextID = 1;
          return ClassInfo;
        }(Info);
      ABC.ClassInfo = ClassInfo;
      var ScriptInfo = function (_super) {
          __extends(ScriptInfo, _super);
          function ScriptInfo(abc, index, stream) {
            _super.call(this, abc, index);
            this.runtimeId = ClassInfo.nextID++;
            this.hash = abc.hash + 131072 + index;
            this.name = abc.name + '$script' + index;
            this.init = abc.methods[stream.readU30()];
            this.init.isScriptInitializer = true;
            AbcFile.attachHolder(this.init, this);
            this.traits = Trait.parseTraits(abc, stream, this);
          }
          Object.defineProperty(ScriptInfo.prototype, 'entryPoint', {
            get: function () {
              return this.init;
            },
            enumerable: true,
            configurable: true
          });
          ScriptInfo.prototype.toString = function () {
            return this.name;
          };
          ScriptInfo.nextID = 1;
          return ScriptInfo;
        }(Info);
      ABC.ScriptInfo = ScriptInfo;
      var AbcFile = function () {
          function AbcFile(bytes, name, hash) {
            if (typeof hash === 'undefined') {
              hash = 0;
            }
            Timer.start('Parse ABC');
            this.name = name;
            this.env = {};
            var computedHash;
            if (!hash || !true) {
              Timer.start('Adler');
              computedHash = Shumway.HashUtilities.hashBytesTo32BitsAdler(bytes, 0, bytes.length);
              Timer.stop();
            }
            if (hash) {
              this.hash = hash;
              true;
            } else {
              this.hash = computedHash;
            }
            var n, i;
            var stream = new AbcStream(bytes);
            AbcFile._checkMagic(stream);
            Timer.start('Parse constantPool');
            this.constantPool = new ConstantPool(stream, this);
            Timer.stop();
            Timer.start('Parse Method Infos');
            this.methods = [];
            n = stream.readU30();
            for (i = 0; i < n; ++i) {
              this.methods.push(new MethodInfo(this, i, stream));
            }
            Timer.stop();
            Timer.start('Parse MetaData Infos');
            this.metadata = [];
            n = stream.readU30();
            for (i = 0; i < n; ++i) {
              this.metadata.push(new MetaDataInfo(this, stream));
            }
            Timer.stop();
            Timer.start('Parse Instance Infos');
            this.instances = [];
            n = stream.readU30();
            for (i = 0; i < n; ++i) {
              this.instances.push(new InstanceInfo(this, i, stream));
            }
            Timer.stop();
            Timer.start('Parse Class Infos');
            this.classes = [];
            for (i = 0; i < n; ++i) {
              this.classes.push(new ClassInfo(this, i, stream));
            }
            Timer.stop();
            Timer.start('Parse Script Infos');
            this.scripts = [];
            n = stream.readU30();
            for (i = 0; i < n; ++i) {
              this.scripts.push(new ScriptInfo(this, i, stream));
            }
            Timer.stop();
            Timer.start('Parse Method Body Info');
            n = stream.readU30();
            for (i = 0; i < n; ++i) {
              MethodInfo.parseBody(this, stream);
            }
            Timer.stop();
            Timer.stop();
          }
          AbcFile._checkMagic = function (stream) {
            var magic = stream.readWord();
            var flashPlayerBrannan = 46 << 16 | 15;
            if (magic < flashPlayerBrannan) {
              throw new Error('Invalid ABC File (magic = ' + Number(magic).toString(16) + ')');
            }
          };
          Object.defineProperty(AbcFile.prototype, 'lastScript', {
            get: function () {
              true;
              return this.scripts[this.scripts.length - 1];
            },
            enumerable: true,
            configurable: true
          });
          AbcFile.attachHolder = function (mi, holder) {
            true;
            mi.holder = holder;
          };
          AbcFile.prototype.toString = function () {
            return this.name;
          };
          return AbcFile;
        }();
      ABC.AbcFile = AbcFile;
      var Namespace = function () {
          function Namespace(kind, uri, prefix, uniqueURIHash) {
            if (typeof uri === 'undefined') {
              uri = '';
            }
            if (uri === undefined) {
              uri = '';
            }
            if (prefix !== undefined) {
              this.prefix = prefix;
            }
            this.kind = kind;
            this.uri = uri;
            this._buildNamespace(uniqueURIHash);
          }
          Namespace.prototype._buildNamespace = function (uniqueURIHash) {
            if (this.kind === 22) {
              this.kind = 8;
            }
            if (this.isPublic() && this.uri) {
              var n = this.uri.length - 1;
              var mark = this.uri.charCodeAt(n);
              if (mark > Namespace._MIN_API_MARK) {
                this.uri = this.uri.substring(0, n - 1);
              }
            } else if (this.isUnique()) {
              this.uri = 'private ' + uniqueURIHash;
            }
            this.qualifiedName = Namespace._qualifyNamespace(this.kind, this.uri, this.prefix ? this.prefix : '');
          };
          Namespace._hashNamespace = function (kind, uri, prefix) {
            var data = new Int32Array(1 + uri.length + prefix.length);
            var j = 0;
            data[j++] = kind;
            var index = Namespace._knownURIs.indexOf(uri);
            if (index >= 0) {
              return kind << 2 | index;
            } else {
              for (var i = 0; i < uri.length; i++) {
                data[j++] = uri.charCodeAt(i);
              }
            }
            for (var i = 0; i < prefix.length; i++) {
              data[j++] = prefix.charCodeAt(i);
            }
            return Shumway.HashUtilities.hashBytesTo32BitsMD5(data, 0, j);
          };
          Namespace._qualifyNamespace = function (kind, uri, prefix) {
            var key = kind + uri;
            var mangledNamespace = Namespace._mangledNamespaceCache[key];
            if (mangledNamespace) {
              return mangledNamespace;
            }
            mangledNamespace = Shumway.StringUtilities.variableLengthEncodeInt32(Namespace._hashNamespace(kind, uri, prefix));
            Namespace._mangledNamespaceMap[mangledNamespace] = {
              kind: kind,
              uri: uri,
              prefix: prefix
            };
            Namespace._mangledNamespaceCache[key] = mangledNamespace;
            return mangledNamespace;
          };
          Namespace.fromQualifiedName = function (qn) {
            var length = Shumway.StringUtilities.fromEncoding(qn[0]);
            var mangledNamespace = qn.substring(0, length + 1);
            var ns = Namespace._mangledNamespaceMap[mangledNamespace];
            return new Namespace(ns.kind, ns.uri, ns.prefix);
          };
          Namespace.kindFromString = function (str) {
            for (var kind in Namespace._kinds) {
              if (Namespace._kinds[kind] === str) {
                return kind;
              }
            }
            return true;
          };
          Namespace.createNamespace = function (uri, prefix) {
            return new Namespace(8, uri, prefix);
          };
          Namespace.parse = function (constantPool, stream, hash) {
            var kind = stream.readU8();
            var uri = constantPool.strings[stream.readU30()];
            return new Namespace(kind, uri, undefined, hash);
          };
          Namespace.prototype.isPublic = function () {
            return this.kind === 8 || this.kind === 22;
          };
          Namespace.prototype.isProtected = function () {
            return this.kind === 24;
          };
          Namespace.prototype.isUnique = function () {
            return this.kind === 5 && !this.uri;
          };
          Namespace.prototype.isDynamic = function () {
            return this.isPublic() && !this.uri;
          };
          Namespace.prototype.getURI = function () {
            return this.uri;
          };
          Namespace.prototype.toString = function () {
            return Namespace._kinds[this.kind] + (this.uri ? ' ' + this.uri : '');
          };
          Namespace.prototype.clone = function () {
            var ns = Object.create(Namespace.prototype);
            ns.kind = this.kind;
            ns.uri = this.uri;
            ns.prefix = this.prefix;
            ns.qualifiedName = this.qualifiedName;
            return ns;
          };
          Namespace.prototype.isEqualTo = function (other) {
            return this.qualifiedName === other.qualifiedName;
          };
          Namespace.prototype.inNamespaceSet = function (set) {
            for (var i = 0; i < set.length; i++) {
              if (set[i].qualifiedName === this.qualifiedName) {
                return true;
              }
            }
            return false;
          };
          Namespace.prototype.getAccessModifier = function () {
            return Namespace._kinds[this.kind];
          };
          Namespace.prototype.getQualifiedName = function () {
            return this.qualifiedName;
          };
          Namespace.fromSimpleName = function (simpleName) {
            if (simpleName in Namespace._simpleNameCache) {
              return Namespace._simpleNameCache[simpleName];
            }
            var namespaceNames;
            if (simpleName.indexOf('[') === 0) {
              true;
              namespaceNames = simpleName.substring(1, simpleName.length - 1).split(',');
            } else {
              namespaceNames = [
                simpleName
              ];
            }
            return Namespace._simpleNameCache[simpleName] = namespaceNames.map(function (name) {
              name = name.trim();
              var kindName, uri;
              if (name.indexOf(' ') > 0) {
                kindName = name.substring(0, name.indexOf(' ')).trim();
                uri = name.substring(name.indexOf(' ') + 1).trim();
              } else {
                var kinds = Namespace._kinds;
                if (name === kinds[8] || name === kinds[23] || name === kinds[5] || name === kinds[24] || name === kinds[25] || name === kinds[26]) {
                  kindName = name;
                  uri = '';
                } else {
                  kindName = Namespace._publicPrefix;
                  uri = name;
                }
              }
              return new Namespace(Namespace.kindFromString(kindName), uri);
            });
          };
          Namespace._publicPrefix = 'public';
          Namespace._kinds = function () {
            var map = Shumway.ObjectUtilities.createMap();
            map[8] = Namespace._publicPrefix;
            map[23] = 'packageInternal';
            map[5] = 'private';
            map[24] = 'protected';
            map[25] = 'explicit';
            map[26] = 'staticProtected';
            return map;
          }();
          Namespace._MIN_API_MARK = 58004;
          Namespace._MAX_API_MARK = 63743;
          Namespace._knownURIs = [
            ''
          ];
          Namespace._mangledNamespaceCache = Shumway.ObjectUtilities.createMap();
          Namespace._mangledNamespaceMap = Shumway.ObjectUtilities.createMap();
          Namespace.PUBLIC = new Namespace(8);
          Namespace.PROTECTED = new Namespace(24);
          Namespace.PROXY = new Namespace(8, 'http://www.adobe.com/2006/actionscript/flash/proxy');
          Namespace._simpleNameCache = Shumway.ObjectUtilities.createMap();
          return Namespace;
        }();
      ABC.Namespace = Namespace;
      var Multiname = function () {
          function Multiname(namespaces, name, flags) {
            if (typeof flags === 'undefined') {
              flags = 0;
            }
            if (name !== undefined) {
              true;
            }
            this.runtimeId = Multiname._nextID++;
            this.namespaces = namespaces;
            this.name = name;
            this.flags = flags;
          }
          Multiname.parse = function (constantPool, stream, multinames, patchFactoryTypes) {
            var index = 0;
            var kind = stream.readU8();
            var name, namespaces = [], flags = 0;
            switch (kind) {
            case 7:
            case 13:
              index = stream.readU30();
              if (index) {
                namespaces = [
                  constantPool.namespaces[index]
                ];
              } else {
                flags &= ~Multiname.RUNTIME_NAME;
              }
              index = stream.readU30();
              if (index) {
                name = constantPool.strings[index];
              }
              break;
            case 15:
            case 16:
              index = stream.readU30();
              if (index) {
                name = constantPool.strings[index];
              } else {
                flags &= ~Multiname.RUNTIME_NAME;
              }
              flags |= Multiname.RUNTIME_NAMESPACE;
              break;
            case 17:
            case 18:
              flags |= Multiname.RUNTIME_NAMESPACE;
              flags |= Multiname.RUNTIME_NAME;
              break;
            case 9:
            case 14:
              index = stream.readU30();
              if (index) {
                name = constantPool.strings[index];
              } else {
                flags &= ~Multiname.RUNTIME_NAME;
              }
              index = stream.readU30();
              true;
              namespaces = constantPool.namespaceSets[index];
              break;
            case 27:
            case 28:
              flags |= Multiname.RUNTIME_NAME;
              index = stream.readU30();
              true;
              namespaces = constantPool.namespaceSets[index];
              break;
            case 29:
              var factoryTypeIndex = stream.readU32();
              if (multinames[factoryTypeIndex]) {
                namespaces = multinames[factoryTypeIndex].namespaces;
                name = multinames[factoryTypeIndex].name;
              }
              var typeParameterCount = stream.readU32();
              true;
              var typeParameterIndex = stream.readU32();
              true;
              var mn = new Multiname(namespaces, name, flags);
              mn.typeParameter = multinames[typeParameterIndex];
              if (!multinames[factoryTypeIndex]) {
                patchFactoryTypes.push({
                  multiname: mn,
                  index: factoryTypeIndex
                });
              }
              return mn;
            default:
              Shumway.Debug.unexpected();
              break;
            }
            switch (kind) {
            case 13:
            case 16:
            case 18:
            case 14:
            case 28:
              flags |= Multiname.ATTRIBUTE;
              break;
            }
            return new Multiname(namespaces, name, flags);
          };
          Multiname.isMultiname = function (mn) {
            return typeof mn === 'number' || typeof mn === 'string' || mn instanceof Multiname || mn instanceof Number;
          };
          Multiname.needsResolution = function (mn) {
            return mn instanceof Multiname && mn.namespaces.length > 1;
          };
          Multiname.isQName = function (mn) {
            if (mn instanceof Multiname) {
              return mn.namespaces && mn.namespaces.length === 1;
            }
            return true;
          };
          Multiname.isRuntimeName = function (mn) {
            return mn instanceof Multiname && mn.isRuntimeName();
          };
          Multiname.isRuntimeNamespace = function (mn) {
            return mn instanceof Multiname && mn.isRuntimeNamespace();
          };
          Multiname.isRuntime = function (mn) {
            return mn instanceof Multiname && mn.isRuntimeName() || mn.isRuntimeNamespace();
          };
          Multiname.getQualifiedName = function (mn) {
            true;
            if (mn instanceof Multiname) {
              if (mn.qualifiedName !== undefined) {
                return mn.qualifiedName;
              }
              var name = String(mn.name);
              if (isNumeric(name) && mn.namespaces[0].isPublic()) {
                return mn.qualifiedName = name;
              }
              mn = mn.qualifiedName = Multiname.qualifyName(mn.namespaces[0], name);
            }
            return mn;
          };
          Multiname.qualifyName = function (namespace, name) {
            return '$' + namespace.qualifiedName + name;
          };
          Multiname.stripPublicQualifier = function (qn) {
            var publicQualifier = '$' + Namespace.PUBLIC.qualifiedName;
            var index = qn.indexOf(publicQualifier);
            if (index !== 0) {
              return undefined;
            }
            return qn.substring(publicQualifier.length);
          };
          Multiname.fromQualifiedName = function (qn) {
            if (qn instanceof Multiname) {
              return qn;
            }
            if (isNumeric(qn)) {
              return new Multiname([
                Namespace.PUBLIC
              ], qn);
            }
            if (qn[0] !== '$') {
              return;
            }
            var ns = Namespace.fromQualifiedName(qn.substring(1));
            return new Multiname([
              ns
            ], qn.substring(1 + ns.qualifiedName.length));
          };
          Multiname.getNameFromPublicQualifiedName = function (qn) {
            var mn = Multiname.fromQualifiedName(qn);
            true;
            return mn.name;
          };
          Multiname.getFullQualifiedName = function (mn) {
            var qn = Multiname.getQualifiedName(mn);
            if (mn instanceof Multiname && mn.typeParameter) {
              qn += '$' + Multiname.getFullQualifiedName(mn.typeParameter);
            }
            return qn;
          };
          Multiname.getPublicQualifiedName = function (name) {
            if (isNumeric(name)) {
              return Shumway.toNumber(name);
            } else if (name !== null && isObject(name)) {
              return name;
            }
            return Multiname.qualifyName(Namespace.PUBLIC, name);
          };
          Multiname.isPublicQualifiedName = function (qn) {
            return typeof qn === 'number' || isNumeric(qn) || qn.indexOf(Namespace.PUBLIC.qualifiedName) === 1;
          };
          Multiname.getAccessModifier = function (mn) {
            true;
            if (typeof mn === 'number' || typeof mn === 'string' || mn instanceof Number) {
              return 'public';
            }
            true;
            return mn.namespaces[0].getAccessModifier();
          };
          Multiname.isNumeric = function (mn) {
            if (typeof mn === 'number') {
              return true;
            } else if (typeof mn === 'string') {
              return isNumeric(mn);
            }
            return !isNaN(parseInt(Multiname.getName(mn), 10));
          };
          Multiname.getName = function (mn) {
            true;
            true;
            return mn.getName();
          };
          Multiname.isAnyName = function (mn) {
            return typeof mn === 'object' && !mn.isRuntimeName() && !mn.name;
          };
          Multiname.fromSimpleName = function (simpleName) {
            true;
            if (simpleName in Multiname._simpleNameCache) {
              return Multiname._simpleNameCache[simpleName];
            }
            var nameIndex, namespaceIndex, name, namespace;
            nameIndex = simpleName.lastIndexOf('.');
            if (nameIndex <= 0) {
              nameIndex = simpleName.lastIndexOf(' ');
            }
            if (nameIndex > 0 && nameIndex < simpleName.length - 1) {
              name = simpleName.substring(nameIndex + 1).trim();
              namespace = simpleName.substring(0, nameIndex).trim();
            } else {
              name = simpleName;
              namespace = '';
            }
            return Multiname._simpleNameCache[simpleName] = new Multiname(Namespace.fromSimpleName(namespace), name);
          };
          Multiname.prototype.getQName = function (index) {
            true;
            if (!this._qualifiedNameCache) {
              this._qualifiedNameCache = Shumway.ObjectUtilities.createArrayMap();
            }
            var name = this._qualifiedNameCache[index];
            if (!name) {
              name = this._qualifiedNameCache[index] = new Multiname([
                this.namespaces[index]
              ], this.name, this.flags);
            }
            return name;
          };
          Multiname.prototype.hasQName = function (qn) {
            true;
            if (this.name !== qn.name) {
              return false;
            }
            for (var i = 0; i < this.namespaces.length; i++) {
              if (this.namespaces[i].isEqualTo(qn.namespaces[0])) {
                return true;
              }
            }
            return false;
          };
          Multiname.prototype.isAttribute = function () {
            return this.flags & Multiname.ATTRIBUTE;
          };
          Multiname.prototype.isAnyName = function () {
            return Multiname.isAnyName(this);
          };
          Multiname.prototype.isAnyNamespace = function () {
            return !this.isRuntimeNamespace() && (this.namespaces.length === 0 || this.isAnyName() && this.namespaces.length !== 1);
          };
          Multiname.prototype.isRuntimeName = function () {
            return !(!(this.flags & Multiname.RUNTIME_NAME));
          };
          Multiname.prototype.isRuntimeNamespace = function () {
            return !(!(this.flags & Multiname.RUNTIME_NAMESPACE));
          };
          Multiname.prototype.isRuntime = function () {
            return !(!(this.flags & (Multiname.RUNTIME_NAME | Multiname.RUNTIME_NAMESPACE)));
          };
          Multiname.prototype.isQName = function () {
            return this.namespaces.length === 1 && !this.isAnyName();
          };
          Multiname.prototype.hasTypeParameter = function () {
            return !(!this.typeParameter);
          };
          Multiname.prototype.getName = function () {
            return this.name;
          };
          Multiname.prototype.getOriginalName = function () {
            true;
            var name = this.namespaces[0].uri;
            if (name) {
              name += '.';
            }
            return name + this.name;
          };
          Multiname.prototype.getNamespace = function () {
            true;
            true;
            return this.namespaces[0];
          };
          Multiname.prototype.nameToString = function () {
            if (this.isAnyName()) {
              return '*';
            } else {
              var name = this.getName();
              return this.isRuntimeName() ? '[]' : name;
            }
          };
          Multiname.prototype.hasObjectName = function () {
            return typeof this.name === 'object';
          };
          Multiname.prototype.toString = function () {
            var str = this.isAttribute() ? '@' : '';
            if (this.isAnyNamespace()) {
              str += '*::' + this.nameToString();
            } else if (this.isRuntimeNamespace()) {
              str += '[]::' + this.nameToString();
            } else if (this.namespaces.length === 1 && this.isQName()) {
              str += this.namespaces[0].toString() + '::';
              str += this.nameToString();
            } else {
              str += '{';
              for (var i = 0, count = this.namespaces.length; i < count; i++) {
                str += this.namespaces[i].toString();
                if (i + 1 < count) {
                  str += ',';
                }
              }
              str += '}::' + this.nameToString();
            }
            if (this.hasTypeParameter()) {
              str += '<' + this.typeParameter.toString() + '>';
            }
            return str;
          };
          Multiname.ATTRIBUTE = 1;
          Multiname.RUNTIME_NAMESPACE = 2;
          Multiname.RUNTIME_NAME = 4;
          Multiname._nextID = 0;
          Multiname._simpleNameCache = Shumway.ObjectUtilities.createMap();
          Multiname.Int = Multiname.getPublicQualifiedName('int');
          Multiname.Uint = Multiname.getPublicQualifiedName('uint');
          Multiname.Class = Multiname.getPublicQualifiedName('Class');
          Multiname.Array = Multiname.getPublicQualifiedName('Array');
          Multiname.Object = Multiname.getPublicQualifiedName('Object');
          Multiname.String = Multiname.getPublicQualifiedName('String');
          Multiname.Number = Multiname.getPublicQualifiedName('Number');
          Multiname.Boolean = Multiname.getPublicQualifiedName('Boolean');
          Multiname.Function = Multiname.getPublicQualifiedName('Function');
          Multiname.XML = Multiname.getPublicQualifiedName('XML');
          Multiname.XMLList = Multiname.getPublicQualifiedName('XMLList');
          Multiname.TEMPORARY = new Multiname([], '');
          return Multiname;
        }();
      ABC.Multiname = Multiname;
      var MetaDataInfo = function () {
          function MetaDataInfo(abc, stream) {
            var strings = abc.constantPool.strings;
            var name = this.name = strings[stream.readU30()];
            var itemCount = stream.readU30();
            var keys = [];
            var items = [];
            for (var i = 0; i < itemCount; i++) {
              keys[i] = strings[stream.readU30()];
            }
            for (var i = 0; i < itemCount; i++) {
              var key = keys[i];
              items[i] = {
                key: key,
                value: strings[stream.readU30()]
              };
              if (key && name === 'native') {
                true;
                this[key] = items[i].value;
              }
            }
            this.value = items;
          }
          MetaDataInfo.prototype.toString = function () {
            return '[' + this.name + ']';
          };
          return MetaDataInfo;
        }();
      ABC.MetaDataInfo = MetaDataInfo;
      (function (CONSTANT) {
        CONSTANT[CONSTANT['Undefined'] = 0] = 'Undefined';
        CONSTANT[CONSTANT['Utf8'] = 1] = 'Utf8';
        CONSTANT[CONSTANT['Float'] = 2] = 'Float';
        CONSTANT[CONSTANT['Int'] = 3] = 'Int';
        CONSTANT[CONSTANT['UInt'] = 4] = 'UInt';
        CONSTANT[CONSTANT['PrivateNs'] = 5] = 'PrivateNs';
        CONSTANT[CONSTANT['Double'] = 6] = 'Double';
        CONSTANT[CONSTANT['QName'] = 7] = 'QName';
        CONSTANT[CONSTANT['Namespace'] = 8] = 'Namespace';
        CONSTANT[CONSTANT['Multiname'] = 9] = 'Multiname';
        CONSTANT[CONSTANT['False'] = 10] = 'False';
        CONSTANT[CONSTANT['True'] = 11] = 'True';
        CONSTANT[CONSTANT['Null'] = 12] = 'Null';
        CONSTANT[CONSTANT['QNameA'] = 13] = 'QNameA';
        CONSTANT[CONSTANT['MultinameA'] = 14] = 'MultinameA';
        CONSTANT[CONSTANT['RTQName'] = 15] = 'RTQName';
        CONSTANT[CONSTANT['RTQNameA'] = 16] = 'RTQNameA';
        CONSTANT[CONSTANT['RTQNameL'] = 17] = 'RTQNameL';
        CONSTANT[CONSTANT['RTQNameLA'] = 18] = 'RTQNameLA';
        CONSTANT[CONSTANT['NameL'] = 19] = 'NameL';
        CONSTANT[CONSTANT['NameLA'] = 20] = 'NameLA';
        CONSTANT[CONSTANT['NamespaceSet'] = 21] = 'NamespaceSet';
        CONSTANT[CONSTANT['PackageNamespace'] = 22] = 'PackageNamespace';
        CONSTANT[CONSTANT['PackageInternalNs'] = 23] = 'PackageInternalNs';
        CONSTANT[CONSTANT['ProtectedNamespace'] = 24] = 'ProtectedNamespace';
        CONSTANT[CONSTANT['ExplicitNamespace'] = 25] = 'ExplicitNamespace';
        CONSTANT[CONSTANT['StaticProtectedNs'] = 26] = 'StaticProtectedNs';
        CONSTANT[CONSTANT['MultinameL'] = 27] = 'MultinameL';
        CONSTANT[CONSTANT['MultinameLA'] = 28] = 'MultinameLA';
        CONSTANT[CONSTANT['TypeName'] = 29] = 'TypeName';
        CONSTANT[CONSTANT['ClassSealed'] = 1] = 'ClassSealed';
        CONSTANT[CONSTANT['ClassFinal'] = 2] = 'ClassFinal';
        CONSTANT[CONSTANT['ClassInterface'] = 4] = 'ClassInterface';
        CONSTANT[CONSTANT['ClassProtectedNs'] = 8] = 'ClassProtectedNs';
      }(ABC.CONSTANT || (ABC.CONSTANT = {})));
      var CONSTANT = ABC.CONSTANT;
      (function (METHOD) {
        METHOD[METHOD['Arguments'] = 1] = 'Arguments';
        METHOD[METHOD['Activation'] = 2] = 'Activation';
        METHOD[METHOD['Needrest'] = 4] = 'Needrest';
        METHOD[METHOD['HasOptional'] = 8] = 'HasOptional';
        METHOD[METHOD['IgnoreRest'] = 16] = 'IgnoreRest';
        METHOD[METHOD['Native'] = 32] = 'Native';
        METHOD[METHOD['Setsdxns'] = 64] = 'Setsdxns';
        METHOD[METHOD['HasParamNames'] = 128] = 'HasParamNames';
      }(ABC.METHOD || (ABC.METHOD = {})));
      var METHOD = ABC.METHOD;
      (function (TRAIT) {
        TRAIT[TRAIT['Slot'] = 0] = 'Slot';
        TRAIT[TRAIT['Method'] = 1] = 'Method';
        TRAIT[TRAIT['Getter'] = 2] = 'Getter';
        TRAIT[TRAIT['Setter'] = 3] = 'Setter';
        TRAIT[TRAIT['Class'] = 4] = 'Class';
        TRAIT[TRAIT['Function'] = 5] = 'Function';
        TRAIT[TRAIT['Const'] = 6] = 'Const';
      }(ABC.TRAIT || (ABC.TRAIT = {})));
      var TRAIT = ABC.TRAIT;
      (function (ATTR) {
        ATTR[ATTR['Final'] = 1] = 'Final';
        ATTR[ATTR['Override'] = 2] = 'Override';
        ATTR[ATTR['Metadata'] = 4] = 'Metadata';
      }(ABC.ATTR || (ABC.ATTR = {})));
      var ATTR = ABC.ATTR;
      (function (SORT) {
        SORT[SORT['CASEINSENSITIVE'] = 1] = 'CASEINSENSITIVE';
        SORT[SORT['DESCENDING'] = 2] = 'DESCENDING';
        SORT[SORT['UNIQUESORT'] = 4] = 'UNIQUESORT';
        SORT[SORT['RETURNINDEXEDARRAY'] = 8] = 'RETURNINDEXEDARRAY';
        SORT[SORT['NUMERIC'] = 16] = 'NUMERIC';
      }(ABC.SORT || (ABC.SORT = {})));
      var SORT = ABC.SORT;
      (function (OP) {
        OP[OP['bkpt'] = 1] = 'bkpt';
        OP[OP['nop'] = 2] = 'nop';
        OP[OP['throw'] = 3] = 'throw';
        OP[OP['getsuper'] = 4] = 'getsuper';
        OP[OP['setsuper'] = 5] = 'setsuper';
        OP[OP['dxns'] = 6] = 'dxns';
        OP[OP['dxnslate'] = 7] = 'dxnslate';
        OP[OP['kill'] = 8] = 'kill';
        OP[OP['label'] = 9] = 'label';
        OP[OP['lf32x4'] = 10] = 'lf32x4';
        OP[OP['sf32x4'] = 11] = 'sf32x4';
        OP[OP['ifnlt'] = 12] = 'ifnlt';
        OP[OP['ifnle'] = 13] = 'ifnle';
        OP[OP['ifngt'] = 14] = 'ifngt';
        OP[OP['ifnge'] = 15] = 'ifnge';
        OP[OP['jump'] = 16] = 'jump';
        OP[OP['iftrue'] = 17] = 'iftrue';
        OP[OP['iffalse'] = 18] = 'iffalse';
        OP[OP['ifeq'] = 19] = 'ifeq';
        OP[OP['ifne'] = 20] = 'ifne';
        OP[OP['iflt'] = 21] = 'iflt';
        OP[OP['ifle'] = 22] = 'ifle';
        OP[OP['ifgt'] = 23] = 'ifgt';
        OP[OP['ifge'] = 24] = 'ifge';
        OP[OP['ifstricteq'] = 25] = 'ifstricteq';
        OP[OP['ifstrictne'] = 26] = 'ifstrictne';
        OP[OP['lookupswitch'] = 27] = 'lookupswitch';
        OP[OP['pushwith'] = 28] = 'pushwith';
        OP[OP['popscope'] = 29] = 'popscope';
        OP[OP['nextname'] = 30] = 'nextname';
        OP[OP['hasnext'] = 31] = 'hasnext';
        OP[OP['pushnull'] = 32] = 'pushnull';
        OP[OP['c'] = 33] = 'c';
        OP[OP['pushundefined'] = 33] = 'pushundefined';
        OP[OP['pushfloat'] = 34] = 'pushfloat';
        OP[OP['nextvalue'] = 35] = 'nextvalue';
        OP[OP['pushbyte'] = 36] = 'pushbyte';
        OP[OP['pushshort'] = 37] = 'pushshort';
        OP[OP['pushtrue'] = 38] = 'pushtrue';
        OP[OP['pushfalse'] = 39] = 'pushfalse';
        OP[OP['pushnan'] = 40] = 'pushnan';
        OP[OP['pop'] = 41] = 'pop';
        OP[OP['dup'] = 42] = 'dup';
        OP[OP['swap'] = 43] = 'swap';
        OP[OP['pushstring'] = 44] = 'pushstring';
        OP[OP['pushint'] = 45] = 'pushint';
        OP[OP['pushuint'] = 46] = 'pushuint';
        OP[OP['pushdouble'] = 47] = 'pushdouble';
        OP[OP['pushscope'] = 48] = 'pushscope';
        OP[OP['pushnamespace'] = 49] = 'pushnamespace';
        OP[OP['hasnext2'] = 50] = 'hasnext2';
        OP[OP['li8'] = 53] = 'li8';
        OP[OP['li16'] = 54] = 'li16';
        OP[OP['li32'] = 55] = 'li32';
        OP[OP['lf32'] = 56] = 'lf32';
        OP[OP['lf64'] = 57] = 'lf64';
        OP[OP['si8'] = 58] = 'si8';
        OP[OP['si16'] = 59] = 'si16';
        OP[OP['si32'] = 60] = 'si32';
        OP[OP['sf32'] = 61] = 'sf32';
        OP[OP['sf64'] = 62] = 'sf64';
        OP[OP['newfunction'] = 64] = 'newfunction';
        OP[OP['call'] = 65] = 'call';
        OP[OP['construct'] = 66] = 'construct';
        OP[OP['callmethod'] = 67] = 'callmethod';
        OP[OP['callstatic'] = 68] = 'callstatic';
        OP[OP['callsuper'] = 69] = 'callsuper';
        OP[OP['callproperty'] = 70] = 'callproperty';
        OP[OP['returnvoid'] = 71] = 'returnvoid';
        OP[OP['returnvalue'] = 72] = 'returnvalue';
        OP[OP['constructsuper'] = 73] = 'constructsuper';
        OP[OP['constructprop'] = 74] = 'constructprop';
        OP[OP['callsuperid'] = 75] = 'callsuperid';
        OP[OP['callproplex'] = 76] = 'callproplex';
        OP[OP['callinterface'] = 77] = 'callinterface';
        OP[OP['callsupervoid'] = 78] = 'callsupervoid';
        OP[OP['callpropvoid'] = 79] = 'callpropvoid';
        OP[OP['sxi1'] = 80] = 'sxi1';
        OP[OP['sxi8'] = 81] = 'sxi8';
        OP[OP['sxi16'] = 82] = 'sxi16';
        OP[OP['applytype'] = 83] = 'applytype';
        OP[OP['pushfloat4'] = 84] = 'pushfloat4';
        OP[OP['newobject'] = 85] = 'newobject';
        OP[OP['newarray'] = 86] = 'newarray';
        OP[OP['newactivation'] = 87] = 'newactivation';
        OP[OP['newclass'] = 88] = 'newclass';
        OP[OP['getdescendants'] = 89] = 'getdescendants';
        OP[OP['newcatch'] = 90] = 'newcatch';
        OP[OP['findpropstrict'] = 93] = 'findpropstrict';
        OP[OP['findproperty'] = 94] = 'findproperty';
        OP[OP['finddef'] = 95] = 'finddef';
        OP[OP['getlex'] = 96] = 'getlex';
        OP[OP['setproperty'] = 97] = 'setproperty';
        OP[OP['getlocal'] = 98] = 'getlocal';
        OP[OP['setlocal'] = 99] = 'setlocal';
        OP[OP['getglobalscope'] = 100] = 'getglobalscope';
        OP[OP['getscopeobject'] = 101] = 'getscopeobject';
        OP[OP['getproperty'] = 102] = 'getproperty';
        OP[OP['getouterscope'] = 103] = 'getouterscope';
        OP[OP['initproperty'] = 104] = 'initproperty';
        OP[OP['setpropertylate'] = 105] = 'setpropertylate';
        OP[OP['deleteproperty'] = 106] = 'deleteproperty';
        OP[OP['deletepropertylate'] = 107] = 'deletepropertylate';
        OP[OP['getslot'] = 108] = 'getslot';
        OP[OP['setslot'] = 109] = 'setslot';
        OP[OP['getglobalslot'] = 110] = 'getglobalslot';
        OP[OP['setglobalslot'] = 111] = 'setglobalslot';
        OP[OP['convert_s'] = 112] = 'convert_s';
        OP[OP['esc_xelem'] = 113] = 'esc_xelem';
        OP[OP['esc_xattr'] = 114] = 'esc_xattr';
        OP[OP['convert_i'] = 115] = 'convert_i';
        OP[OP['convert_u'] = 116] = 'convert_u';
        OP[OP['convert_d'] = 117] = 'convert_d';
        OP[OP['convert_b'] = 118] = 'convert_b';
        OP[OP['convert_o'] = 119] = 'convert_o';
        OP[OP['checkfilter'] = 120] = 'checkfilter';
        OP[OP['convert_f'] = 121] = 'convert_f';
        OP[OP['unplus'] = 122] = 'unplus';
        OP[OP['convert_f4'] = 123] = 'convert_f4';
        OP[OP['coerce'] = 128] = 'coerce';
        OP[OP['coerce_b'] = 129] = 'coerce_b';
        OP[OP['coerce_a'] = 130] = 'coerce_a';
        OP[OP['coerce_i'] = 131] = 'coerce_i';
        OP[OP['coerce_d'] = 132] = 'coerce_d';
        OP[OP['coerce_s'] = 133] = 'coerce_s';
        OP[OP['astype'] = 134] = 'astype';
        OP[OP['astypelate'] = 135] = 'astypelate';
        OP[OP['coerce_u'] = 136] = 'coerce_u';
        OP[OP['coerce_o'] = 137] = 'coerce_o';
        OP[OP['negate'] = 144] = 'negate';
        OP[OP['increment'] = 145] = 'increment';
        OP[OP['inclocal'] = 146] = 'inclocal';
        OP[OP['decrement'] = 147] = 'decrement';
        OP[OP['declocal'] = 148] = 'declocal';
        OP[OP['typeof'] = 149] = 'typeof';
        OP[OP['not'] = 150] = 'not';
        OP[OP['bitnot'] = 151] = 'bitnot';
        OP[OP['add'] = 160] = 'add';
        OP[OP['subtract'] = 161] = 'subtract';
        OP[OP['multiply'] = 162] = 'multiply';
        OP[OP['divide'] = 163] = 'divide';
        OP[OP['modulo'] = 164] = 'modulo';
        OP[OP['lshift'] = 165] = 'lshift';
        OP[OP['rshift'] = 166] = 'rshift';
        OP[OP['urshift'] = 167] = 'urshift';
        OP[OP['bitand'] = 168] = 'bitand';
        OP[OP['bitor'] = 169] = 'bitor';
        OP[OP['bitxor'] = 170] = 'bitxor';
        OP[OP['equals'] = 171] = 'equals';
        OP[OP['strictequals'] = 172] = 'strictequals';
        OP[OP['lessthan'] = 173] = 'lessthan';
        OP[OP['lessequals'] = 174] = 'lessequals';
        OP[OP['greaterthan'] = 175] = 'greaterthan';
        OP[OP['greaterequals'] = 176] = 'greaterequals';
        OP[OP['instanceof'] = 177] = 'instanceof';
        OP[OP['istype'] = 178] = 'istype';
        OP[OP['istypelate'] = 179] = 'istypelate';
        OP[OP['in'] = 180] = 'in';
        OP[OP['increment_i'] = 192] = 'increment_i';
        OP[OP['decrement_i'] = 193] = 'decrement_i';
        OP[OP['inclocal_i'] = 194] = 'inclocal_i';
        OP[OP['declocal_i'] = 195] = 'declocal_i';
        OP[OP['negate_i'] = 196] = 'negate_i';
        OP[OP['add_i'] = 197] = 'add_i';
        OP[OP['subtract_i'] = 198] = 'subtract_i';
        OP[OP['multiply_i'] = 199] = 'multiply_i';
        OP[OP['getlocal0'] = 208] = 'getlocal0';
        OP[OP['getlocal1'] = 209] = 'getlocal1';
        OP[OP['getlocal2'] = 210] = 'getlocal2';
        OP[OP['getlocal3'] = 211] = 'getlocal3';
        OP[OP['setlocal0'] = 212] = 'setlocal0';
        OP[OP['setlocal1'] = 213] = 'setlocal1';
        OP[OP['setlocal2'] = 214] = 'setlocal2';
        OP[OP['setlocal3'] = 215] = 'setlocal3';
        OP[OP['invalid'] = 237] = 'invalid';
        OP[OP['debug'] = 239] = 'debug';
        OP[OP['debugline'] = 240] = 'debugline';
        OP[OP['debugfile'] = 241] = 'debugfile';
        OP[OP['bkptline'] = 242] = 'bkptline';
        OP[OP['timestamp'] = 243] = 'timestamp';
      }(ABC.OP || (ABC.OP = {})));
      var OP = ABC.OP;
      var ConstantPool = function () {
          function ConstantPool(stream, abc) {
            var n;
            var ints = [
                0
              ];
            n = stream.readU30();
            for (var i = 1; i < n; ++i) {
              ints.push(stream.readS32());
            }
            var uints = [
                0
              ];
            n = stream.readU30();
            for (var i = 1; i < n; ++i) {
              uints.push(stream.readU32());
            }
            var doubles = [
                NaN
              ];
            n = stream.readU30();
            for (var i = 1; i < n; ++i) {
              doubles.push(stream.readDouble());
            }
            Timer.start('Parse Strings');
            var strings = [
                ''
              ];
            n = stream.readU30();
            for (var i = 1; i < n; ++i) {
              strings.push(stream.readUTFString(stream.readU30()));
            }
            this.positionAfterUTFStrings = stream.position;
            Timer.stop();
            this.ints = ints;
            this.uints = uints;
            this.doubles = doubles;
            this.strings = strings;
            Timer.start('Parse Namespaces');
            var namespaces = [
                undefined
              ];
            n = stream.readU30();
            for (var i = 1; i < n; ++i) {
              namespaces.push(Namespace.parse(this, stream, abc.hash + i));
            }
            Timer.stop();
            Timer.start('Parse Namespace Sets');
            var namespaceSets = [
                undefined
              ];
            n = stream.readU30();
            for (var i = 1; i < n; ++i) {
              var count = stream.readU30();
              var set = [];
              set.runtimeId = ConstantPool._nextNamespaceSetID++;
              for (var j = 0; j < count; ++j) {
                set.push(namespaces[stream.readU30()]);
              }
              namespaceSets.push(set);
            }
            Timer.stop();
            this.namespaces = namespaces;
            this.namespaceSets = namespaceSets;
            Timer.start('Parse Multinames');
            var multinames = [
                undefined
              ];
            var patchFactoryTypes = [];
            n = stream.readU30();
            for (var i = 1; i < n; ++i) {
              multinames.push(Multiname.parse(this, stream, multinames, patchFactoryTypes));
            }
            Timer.stop();
            this.multinames = multinames;
          }
          ConstantPool.prototype.getValue = function (kind, index) {
            switch (kind) {
            case 3:
              return this.ints[index];
            case 4:
              return this.uints[index];
            case 6:
              return this.doubles[index];
            case 1:
              return this.strings[index];
            case 11:
              return true;
            case 10:
              return false;
            case 12:
              return null;
            case 0:
              return undefined;
            case 8:
            case 23:
              return this.namespaces[index];
            case 7:
            case 14:
            case 15:
            case 16:
            case 17:
            case 18:
            case 19:
            case 20:
              return this.multinames[index];
            case 2:
              Shumway.Debug.warning('TODO: CONSTANT.Float may be deprecated?');
              break;
            default:
              true;
            }
          };
          ConstantPool._nextNamespaceSetID = 1;
          return ConstantPool;
        }();
      ABC.ConstantPool = ConstantPool;
    }(AVM2.ABC || (AVM2.ABC = {})));
    var ABC = AVM2.ABC;
  }(Shumway.AVM2 || (Shumway.AVM2 = {})));
  var AVM2 = Shumway.AVM2;
}(Shumway || (Shumway = {})));
var AbcFile = Shumway.AVM2.ABC.AbcFile;
var AbcStream = Shumway.AVM2.ABC.AbcStream;
var ConstantPool = Shumway.AVM2.ABC.ConstantPool;
var ClassInfo = Shumway.AVM2.ABC.ClassInfo;
var MetaDataInfo = Shumway.AVM2.ABC.MetaDataInfo;
var InstanceInfo = Shumway.AVM2.ABC.InstanceInfo;
var ScriptInfo = Shumway.AVM2.ABC.ScriptInfo;
var Trait = Shumway.AVM2.ABC.Trait;
var MethodInfo = Shumway.AVM2.ABC.MethodInfo;
var Multiname = Shumway.AVM2.ABC.Multiname;
var ASNamespace = Shumway.AVM2.ABC.Namespace;
var AbcFile = Shumway.AVM2.ABC.AbcFile;
var AbcStream = Shumway.AVM2.ABC.AbcStream;
var ConstantPool = Shumway.AVM2.ABC.ConstantPool;
var ClassInfo = Shumway.AVM2.ABC.ClassInfo;
var MetaDataInfo = Shumway.AVM2.ABC.MetaDataInfo;
var InstanceInfo = Shumway.AVM2.ABC.InstanceInfo;
var ScriptInfo = Shumway.AVM2.ABC.ScriptInfo;
var Trait = Shumway.AVM2.ABC.Trait;
var MethodInfo = Shumway.AVM2.ABC.MethodInfo;
var Multiname = Shumway.AVM2.ABC.Multiname;
var ASNamespace = Shumway.AVM2.ABC.Namespace;
var Bytecode = function () {
    function Bytecode(code) {
      var op = code.readU8();
      this.op = op;
      this.originalPosition = code.position;
      var opdesc = Shumway.AVM2.opcodeTable[op];
      if (!opdesc) {
        unexpected('Unknown Op ' + op);
      }
      this.canThrow = opdesc.canThrow;
      var i, n;
      switch (op) {
      case OP_lookupswitch:
        var defaultOffset = code.readS24();
        this.offsets = [];
        var n = code.readU30() + 1;
        for (i = 0; i < n; i++) {
          this.offsets.push(code.readS24());
        }
        this.offsets.push(defaultOffset);
        break;
      default:
        for (i = 0, n = opdesc.operands.length; i < n; i++) {
          var operand = opdesc.operands[i];
          switch (operand.size) {
          case 'u08':
            this[operand.name] = code.readU8();
            break;
          case 's08':
            this[operand.name] = code.readS8();
            break;
          case 's16':
            this[operand.name] = code.readS16();
            break;
          case 's24':
            this[operand.name] = code.readS24();
            break;
          case 'u30':
            this[operand.name] = code.readU30();
            break;
          case 'u32':
            this[operand.name] = code.readU32();
            break;
          default:
            unexpected();
          }
        }
      }
    }
    Bytecode.prototype = {
      makeBlockHead: function makeBlockHead(id) {
        if (this.succs) {
          return id;
        }
        this.bid = id;
        this.succs = [];
        this.preds = [];
        this.dominatees = [];
        return id + 1;
      },
      trace: function trace(writer) {
        if (!this.succs) {
          return;
        }
        writer.writeLn('#' + this.bid);
      },
      toString: function toString(abc) {
        var opDescription = Shumway.AVM2.opcodeTable[this.op];
        var str = opDescription.name.padRight(' ', 20);
        var i, j;
        if (this.op === OP_lookupswitch) {
          str += 'targets:';
          for (i = 0, j = this.targets.length; i < j; i++) {
            str += (i > 0 ? ',' : '') + this.targets[i].position;
          }
        } else {
          for (i = 0, j = opDescription.operands.length; i < j; i++) {
            var operand = opDescription.operands[i];
            if (operand.name === 'offset') {
              str += 'target:' + this.target.position;
            } else {
              str += operand.name + ': ';
              var value = this[operand.name];
              if (abc) {
                switch (operand.type) {
                case '':
                  str += value;
                  break;
                case 'I':
                  str += abc.constantPool.ints[value];
                  break;
                case 'U':
                  str += abc.constantPool.uints[value];
                  break;
                case 'D':
                  str += abc.constantPool.doubles[value];
                  break;
                case 'S':
                  str += abc.constantPool.strings[value];
                  break;
                case 'N':
                  str += abc.constantPool.namespaces[value];
                  break;
                case 'CI':
                  str += abc.classes[value];
                  break;
                case 'M':
                  str += abc.constantPool.multinames[value];
                  break;
                default:
                  str += '?';
                  break;
                }
              } else {
                str += value;
              }
            }
            if (i < j - 1) {
              str += ', ';
            }
          }
        }
        return str;
      }
    };
    return Bytecode;
  }();
var Analysis = function () {
    function blockSetClass(length, blockById) {
      var BlockSet = BitSetFunctor(length);
      var ADDRESS_BITS_PER_WORD = BlockSet.ADDRESS_BITS_PER_WORD;
      var BITS_PER_WORD = BlockSet.BITS_PER_WORD;
      var BIT_INDEX_MASK = BlockSet.BIT_INDEX_MASK;
      BlockSet.singleton = function singleton(b) {
        var bs = new BlockSet();
        bs.set(b.bid);
        bs.count = 1;
        bs.dirty = 0;
        return bs;
      };
      BlockSet.fromBlocks = function fromArray(other) {
        var bs = new BlockSet();
        bs.setBlocks(other);
        return bs;
      };
      var Bsp = BlockSet.prototype;
      if (BlockSet.singleword) {
        Bsp.forEachBlock = function forEach(fn) {
          true;
          var byId = blockById;
          var word = this.bits;
          if (word) {
            for (var k = 0; k < BITS_PER_WORD; k++) {
              if (word & 1 << k) {
                fn(byId[k]);
              }
            }
          }
        };
        Bsp.choose = function choose() {
          var byId = blockById;
          var word = this.bits;
          if (word) {
            for (var k = 0; k < BITS_PER_WORD; k++) {
              if (word & 1 << k) {
                return byId[k];
              }
            }
          }
        };
        Bsp.members = function members() {
          var byId = blockById;
          var set = [];
          var word = this.bits;
          if (word) {
            for (var k = 0; k < BITS_PER_WORD; k++) {
              if (word & 1 << k) {
                set.push(byId[k]);
              }
            }
          }
          return set;
        };
        Bsp.setBlocks = function setBlocks(bs) {
          var bits = this.bits;
          for (var i = 0, j = bs.length; i < j; i++) {
            var id = bs[i].bid;
            bits |= 1 << (id & BIT_INDEX_MASK);
          }
          this.bits = bits;
        };
      } else {
        Bsp.forEachBlock = function forEach(fn) {
          true;
          var byId = blockById;
          var bits = this.bits;
          for (var i = 0, j = bits.length; i < j; i++) {
            var word = bits[i];
            if (word) {
              for (var k = 0; k < BITS_PER_WORD; k++) {
                if (word & 1 << k) {
                  fn(byId[i * BITS_PER_WORD + k]);
                }
              }
            }
          }
        };
        Bsp.choose = function choose() {
          var byId = blockById;
          var bits = this.bits;
          for (var i = 0, j = bits.length; i < j; i++) {
            var word = bits[i];
            if (word) {
              for (var k = 0; k < BITS_PER_WORD; k++) {
                if (word & 1 << k) {
                  return byId[i * BITS_PER_WORD + k];
                }
              }
            }
          }
        };
        Bsp.members = function members() {
          var byId = blockById;
          var set = [];
          var bits = this.bits;
          for (var i = 0, j = bits.length; i < j; i++) {
            var word = bits[i];
            if (word) {
              for (var k = 0; k < BITS_PER_WORD; k++) {
                if (word & 1 << k) {
                  set.push(byId[i * BITS_PER_WORD + k]);
                }
              }
            }
          }
          return set;
        };
        Bsp.setBlocks = function setBlocks(bs) {
          var bits = this.bits;
          for (var i = 0, j = bs.length; i < j; i++) {
            var id = bs[i].bid;
            bits[id >> ADDRESS_BITS_PER_WORD] |= 1 << (id & BIT_INDEX_MASK);
          }
        };
      }
      return BlockSet;
    }
    function Analysis(method) {
      Counter.count('Analysis');
      this.method = method;
      if (this.method.code) {
        Timer.start('Normalize');
        this.normalizeBytecode();
        Timer.stop();
      }
    }
    Analysis.prototype = {
      normalizeBytecode: function normalizeBytecode() {
        function getInvalidTarget(cache, offset) {
          if (cache && cache[offset]) {
            return cache[offset];
          }
          var code = Object.create(Bytecode.prototype);
          code.op = OP_invalid;
          code.position = offset;
          cache && (cache[offset] = code);
          return code;
        }
        var method = this.method;
        function accessLocal(index) {
          if (index-- === 0)
            return;
          if (index < method.parameters.length) {
            method.parameters[index].isUsed = true;
          }
        }
        var bytecodesOffset = [];
        var bytecodes = [];
        var codeStream = new AbcStream(this.method.code);
        var code;
        while (codeStream.remaining() > 0) {
          var pos = codeStream.position;
          code = new Bytecode(codeStream);
          switch (code.op) {
          case OP_nop:
          case OP_label:
            bytecodesOffset[pos] = bytecodes.length;
            continue;
          case OP_lookupswitch:
            this.method.hasLookupSwitches = true;
            code.targets = [];
            var offsets = code.offsets;
            for (var i = 0, j = offsets.length; i < j; i++) {
              offsets[i] += pos;
            }
            break;
          case OP_jump:
          case OP_iflt:
          case OP_ifnlt:
          case OP_ifle:
          case OP_ifnle:
          case OP_ifgt:
          case OP_ifngt:
          case OP_ifge:
          case OP_ifnge:
          case OP_ifeq:
          case OP_ifne:
          case OP_ifstricteq:
          case OP_ifstrictne:
          case OP_iftrue:
          case OP_iffalse:
            code.offset += codeStream.position;
            break;
          case OP_getlocal0:
          case OP_getlocal1:
          case OP_getlocal2:
          case OP_getlocal3:
            accessLocal(code.op - OP_getlocal0);
            break;
          case OP_getlocal:
            accessLocal(code.index);
            break;
          default:
            break;
          }
          code.position = bytecodes.length;
          bytecodesOffset[pos] = bytecodes.length;
          bytecodes.push(code);
        }
        var invalidJumps = {};
        var newOffset;
        for (var pc = 0, end = bytecodes.length; pc < end; pc++) {
          code = bytecodes[pc];
          switch (code.op) {
          case OP_lookupswitch:
            var offsets = code.offsets;
            for (var i = 0, j = offsets.length; i < j; i++) {
              newOffset = bytecodesOffset[offsets[i]];
              code.targets.push(bytecodes[newOffset] || getInvalidTarget(invalidJumps, offsets[i]));
              offsets[i] = newOffset;
            }
            break;
          case OP_jump:
          case OP_iflt:
          case OP_ifnlt:
          case OP_ifle:
          case OP_ifnle:
          case OP_ifgt:
          case OP_ifngt:
          case OP_ifge:
          case OP_ifnge:
          case OP_ifeq:
          case OP_ifne:
          case OP_ifstricteq:
          case OP_ifstrictne:
          case OP_iftrue:
          case OP_iffalse:
            newOffset = bytecodesOffset[code.offset];
            code.target = bytecodes[newOffset] || getInvalidTarget(invalidJumps, code.offset);
            code.offset = newOffset;
            break;
          default:
          }
        }
        this.bytecodes = bytecodes;
        var exceptions = this.method.exceptions;
        for (var i = 0, j = exceptions.length; i < j; i++) {
          var ex = exceptions[i];
          ex.start = bytecodesOffset[ex.start];
          ex.end = bytecodesOffset[ex.end];
          ex.offset = bytecodesOffset[ex.target];
          ex.target = bytecodes[ex.offset];
          ex.target.exception = ex;
        }
      },
      detectBasicBlocks: function detectBasicBlocks() {
        var bytecodes = this.bytecodes;
        var exceptions = this.method.exceptions;
        var hasExceptions = exceptions.length > 0;
        var blockById = {};
        var code;
        var pc, end;
        var id = 0;
        function tryTargets(block) {
          var targets = [];
          for (var i = 0, j = exceptions.length; i < j; i++) {
            var ex = exceptions[i];
            if (block.position >= ex.start && block.end.position <= ex.end) {
              targets.push(ex.target);
            }
          }
          return targets;
        }
        id = bytecodes[0].makeBlockHead(id);
        for (pc = 0, end = bytecodes.length - 1; pc < end; pc++) {
          code = bytecodes[pc];
          switch (code.op) {
          case OP_returnvoid:
          case OP_returnvalue:
          case OP_throw:
            id = bytecodes[pc + 1].makeBlockHead(id);
            break;
          case OP_lookupswitch:
            var targets = code.targets;
            for (var i = 0, j = targets.length; i < j; i++) {
              id = targets[i].makeBlockHead(id);
            }
            id = bytecodes[pc + 1].makeBlockHead(id);
            break;
          case OP_jump:
          case OP_iflt:
          case OP_ifnlt:
          case OP_ifle:
          case OP_ifnle:
          case OP_ifgt:
          case OP_ifngt:
          case OP_ifge:
          case OP_ifnge:
          case OP_ifeq:
          case OP_ifne:
          case OP_ifstricteq:
          case OP_ifstrictne:
          case OP_iftrue:
          case OP_iffalse:
            id = code.target.makeBlockHead(id);
            id = bytecodes[pc + 1].makeBlockHead(id);
            break;
          default:
          }
        }
        code = bytecodes[end];
        switch (code.op) {
        case OP_returnvoid:
        case OP_returnvalue:
        case OP_throw:
          break;
        case OP_lookupswitch:
          var targets = code.targets;
          for (var i = 0, j = targets.length; i < j; i++) {
            id = targets[i].makeBlockHead(id);
          }
          break;
        case OP_jump:
          id = code.target.makeBlockHead(id);
          break;
        case OP_iflt:
        case OP_ifnlt:
        case OP_ifle:
        case OP_ifnle:
        case OP_ifgt:
        case OP_ifngt:
        case OP_ifge:
        case OP_ifnge:
        case OP_ifeq:
        case OP_ifne:
        case OP_ifstricteq:
        case OP_ifstrictne:
        case OP_iftrue:
        case OP_iffalse:
          id = code.target.makeBlockHead(id);
          bytecodes[pc + 1] = getInvalidTarget(null, pc + 1);
          id = bytecodes[pc + 1].makeBlockHead(id);
          break;
        default:
        }
        if (hasExceptions) {
          for (var i = 0, j = exceptions.length; i < j; i++) {
            var ex = exceptions[i];
            var tryStart = bytecodes[ex.start];
            var afterTry = bytecodes[ex.end + 1];
            id = tryStart.makeBlockHead(id);
            if (afterTry) {
              id = afterTry.makeBlockHead(id);
            }
            id = ex.target.makeBlockHead(id);
          }
        }
        var currentBlock = bytecodes[0];
        for (pc = 1, end = bytecodes.length; pc < end; pc++) {
          if (!bytecodes[pc].succs) {
            continue;
          }
          true;
          blockById[currentBlock.bid] = currentBlock;
          code = bytecodes[pc - 1];
          currentBlock.end = code;
          var nextBlock = bytecodes[pc];
          switch (code.op) {
          case OP_returnvoid:
          case OP_returnvalue:
          case OP_throw:
            break;
          case OP_lookupswitch:
            for (var i = 0, j = code.targets.length; i < j; i++) {
              currentBlock.succs.push(code.targets[i]);
            }
            break;
          case OP_jump:
            currentBlock.succs.push(code.target);
            break;
          case OP_iflt:
          case OP_ifnlt:
          case OP_ifle:
          case OP_ifnle:
          case OP_ifgt:
          case OP_ifngt:
          case OP_ifge:
          case OP_ifnge:
          case OP_ifeq:
          case OP_ifne:
          case OP_ifstricteq:
          case OP_ifstrictne:
          case OP_iftrue:
          case OP_iffalse:
            currentBlock.succs.push(code.target);
            if (code.target !== nextBlock) {
              currentBlock.succs.push(nextBlock);
            }
            break;
          default:
            currentBlock.succs.push(nextBlock);
          }
          if (hasExceptions) {
            var targets = tryTargets(currentBlock);
            currentBlock.hasCatches = targets.length > 0;
            currentBlock.succs.push.apply(currentBlock.succs, targets);
          }
          currentBlock = nextBlock;
        }
        blockById[currentBlock.bid] = currentBlock;
        code = bytecodes[end - 1];
        switch (code.op) {
        case OP_lookupswitch:
          for (var i = 0, j = code.targets.length; i < j; i++) {
            currentBlock.succs.push(code.targets[i]);
          }
          break;
        case OP_jump:
          currentBlock.succs.push(code.target);
          break;
        default:
        }
        currentBlock.end = code;
        this.BlockSet = blockSetClass(id, blockById);
      },
      normalizeReachableBlocks: function normalizeReachableBlocks() {
        var root = this.bytecodes[0];
        true;
        var ONCE = 1;
        var BUNCH_OF_TIMES = 2;
        var BlockSet = this.BlockSet;
        var blocks = [];
        var visited = {};
        var ancestors = {};
        var worklist = [
            root
          ];
        var node;
        ancestors[root.bid] = true;
        while (node = worklist.top()) {
          if (visited[node.bid]) {
            if (visited[node.bid] === ONCE) {
              visited[node.bid] = BUNCH_OF_TIMES;
              blocks.push(node);
              var succs = node.succs;
              for (var i = 0, j = succs.length; i < j; i++) {
                succs[i].preds.push(node);
              }
            }
            ancestors[node.bid] = false;
            worklist.pop();
            continue;
          }
          visited[node.bid] = ONCE;
          ancestors[node.bid] = true;
          var succs = node.succs;
          for (var i = 0, j = succs.length; i < j; i++) {
            var s = succs[i];
            if (ancestors[s.bid]) {
              if (!node.spbacks) {
                node.spbacks = new BlockSet();
              }
              node.spbacks.set(s.bid);
            }
            !visited[s.bid] && worklist.push(s);
          }
        }
        this.blocks = blocks.reverse();
      },
      computeDominance: function computeDominance() {
        function intersectDominators(doms, b1, b2) {
          var finger1 = b1;
          var finger2 = b2;
          while (finger1 !== finger2) {
            while (finger1 > finger2) {
              finger1 = doms[finger1];
            }
            while (finger2 > finger1) {
              finger2 = doms[finger2];
            }
          }
          return finger1;
        }
        var blocks = this.blocks;
        var n = blocks.length;
        var doms = new Array(n);
        doms[0] = 0;
        var rpo = {};
        for (var b = 0; b < n; b++) {
          rpo[blocks[b].bid] = b;
        }
        var changed = true;
        while (changed) {
          changed = false;
          for (var b = 1; b < n; b++) {
            var preds = blocks[b].preds;
            var j = preds.length;
            var newIdom = rpo[preds[0].bid];
            if (!(newIdom in doms)) {
              for (var i = 1; i < j; i++) {
                newIdom = rpo[preds[i].bid];
                if (newIdom in doms) {
                  break;
                }
              }
            }
            true;
            for (var i = 0; i < j; i++) {
              var p = rpo[preds[i].bid];
              if (p === newIdom) {
                continue;
              }
              if (p in doms) {
                newIdom = intersectDominators(doms, p, newIdom);
              }
            }
            if (doms[b] !== newIdom) {
              doms[b] = newIdom;
              changed = true;
            }
          }
        }
        blocks[0].dominator = blocks[0];
        var block;
        for (var b = 1; b < n; b++) {
          block = blocks[b];
          var idom = blocks[doms[b]];
          block.dominator = idom;
          idom.dominatees.push(block);
          block.npreds = block.preds.length;
        }
        var worklist = [
            blocks[0]
          ];
        blocks[0].level || (blocks[0].level = 0);
        while (block = worklist.shift()) {
          var dominatees = block.dominatees;
          for (var i = 0, j = dominatees.length; i < j; i++) {
            dominatees[i].level = block.level + 1;
          }
          worklist.push.apply(worklist, dominatees);
        }
      },
      analyzeControlFlow: function analyzeControlFlow() {
        true;
        this.detectBasicBlocks();
        this.normalizeReachableBlocks();
        this.computeDominance();
        this.analyzedControlFlow = true;
        return true;
      },
      markLoops: function markLoops() {
        if (!this.analyzedControlFlow && !this.analyzeControlFlow()) {
          return false;
        }
        var BlockSet = this.BlockSet;
        function findSCCs(root) {
          var preorderId = 1;
          var preorder = {};
          var assigned = {};
          var unconnectedNodes = [];
          var pendingNodes = [];
          var sccs = [];
          var level = root.level + 1;
          var worklist = [
              root
            ];
          var node;
          var u, s;
          while (node = worklist.top()) {
            if (preorder[node.bid]) {
              if (pendingNodes.peek() === node) {
                pendingNodes.pop();
                var scc = [];
                do {
                  u = unconnectedNodes.pop();
                  assigned[u.bid] = true;
                  scc.push(u);
                } while (u !== node);
                if (scc.length > 1 || u.spbacks && u.spbacks.get(u.bid)) {
                  sccs.push(scc);
                }
              }
              worklist.pop();
              continue;
            }
            preorder[node.bid] = preorderId++;
            unconnectedNodes.push(node);
            pendingNodes.push(node);
            var succs = node.succs;
            for (var i = 0, j = succs.length; i < j; i++) {
              s = succs[i];
              if (s.level < level) {
                continue;
              }
              var sid = s.bid;
              if (!preorder[sid]) {
                worklist.push(s);
              } else if (!assigned[sid]) {
                while (preorder[pendingNodes.peek().bid] > preorder[sid]) {
                  pendingNodes.pop();
                }
              }
            }
          }
          return sccs;
        }
        function findLoopHeads(blocks) {
          var heads = new BlockSet();
          for (var i = 0, j = blocks.length; i < j; i++) {
            var block = blocks[i];
            var spbacks = block.spbacks;
            if (!spbacks) {
              continue;
            }
            var succs = block.succs;
            for (var k = 0, l = succs.length; k < l; k++) {
              var s = succs[k];
              if (spbacks.get(s.bid)) {
                heads.set(s.dominator.bid);
              }
            }
          }
          return heads.members();
        }
        function LoopInfo(scc, loopId) {
          var body = new BlockSet();
          body.setBlocks(scc);
          body.recount();
          this.id = loopId;
          this.body = body;
          this.exit = new BlockSet();
          this.save = {};
          this.head = new BlockSet();
          this.npreds = 0;
        }
        var heads = findLoopHeads(this.blocks);
        if (heads.length <= 0) {
          this.markedLoops = true;
          return true;
        }
        var worklist = heads.sort(function (a, b) {
            return a.level - b.level;
          });
        var loopId = 0;
        for (var n = worklist.length - 1; n >= 0; n--) {
          var top = worklist[n];
          var sccs = findSCCs(top);
          if (sccs.length === 0) {
            continue;
          }
          for (var i = 0, j = sccs.length; i < j; i++) {
            var scc = sccs[i];
            var loop = new LoopInfo(scc, loopId++);
            for (var k = 0, l = scc.length; k < l; k++) {
              var h = scc[k];
              if (h.level === top.level + 1 && !h.loop) {
                h.loop = loop;
                loop.head.set(h.bid);
                var preds = h.preds;
                for (var pi = 0, pj = preds.length; pi < pj; pi++) {
                  loop.body.get(preds[pi].bid) && h.npreds--;
                }
                loop.npreds += h.npreds;
              }
            }
            for (var k = 0, l = scc.length; k < l; k++) {
              var h = scc[k];
              if (h.level === top.level + 1) {
                h.npreds = loop.npreds;
              }
            }
            loop.head.recount();
          }
        }
        this.markedLoops = true;
        return true;
      }
    };
    return Analysis;
  }();
(function (exports) {
  var lang = exports.lang = {
      Node: {},
      Program: {
        extends: 'Node',
        fields: [
          '@body'
        ]
      },
      Statement: {
        extends: 'Node'
      },
      EmptyStatement: {
        extends: 'Statement'
      },
      BlockStatement: {
        extends: 'Statement',
        fields: [
          '@body'
        ]
      },
      ExpressionStatement: {
        extends: 'Statement',
        fields: [
          '@expression'
        ]
      },
      IfStatement: {
        extends: 'Statement',
        fields: [
          '@test',
          '@consequent',
          '@alternate'
        ]
      },
      LabeledStatement: {
        extends: 'Statement',
        fields: [
          '@label',
          '@body'
        ]
      },
      BreakStatement: {
        extends: 'Statement',
        fields: [
          '@label'
        ]
      },
      ContinueStatement: {
        extends: 'Statement',
        fields: [
          '@label'
        ]
      },
      WithStatement: {
        extends: 'Statement',
        fields: [
          '@object',
          '@body'
        ]
      },
      SwitchStatement: {
        extends: 'Statement',
        fields: [
          '@discriminant',
          '@cases',
          'lexical'
        ]
      },
      ReturnStatement: {
        extends: 'Statement',
        fields: [
          '@argument'
        ]
      },
      ThrowStatement: {
        extends: 'Statement',
        fields: [
          '@argument'
        ]
      },
      TryStatement: {
        extends: 'Statement',
        fields: [
          '@block',
          '@handlers',
          '@finalizer'
        ]
      },
      WhileStatement: {
        extends: 'Statement',
        fields: [
          '@test',
          '@body'
        ]
      },
      DoWhileStatement: {
        extends: 'Statement',
        fields: [
          '@body',
          '@test'
        ]
      },
      ForStatement: {
        extends: 'Statement',
        fields: [
          '@init',
          '@test',
          '@update',
          '@body'
        ]
      },
      ForInStatement: {
        extends: 'Statement',
        fields: [
          '@left',
          '@right',
          '@body',
          'each'
        ]
      },
      LetStatement: {
        extends: 'Statement',
        fields: [
          '@head',
          '@body'
        ]
      },
      DebuggerStatement: {
        extends: 'Statement'
      },
      Declaration: {
        extends: 'Statement'
      },
      FunctionDeclaration: {
        extends: 'Declaration',
        fields: [
          '@id',
          '@params',
          '@body',
          '@decltype',
          'generator',
          'expression',
          '@modifiers'
        ]
      },
      VariableDeclaration: {
        extends: 'Declaration',
        fields: [
          'kind',
          '@declarations'
        ]
      },
      VariableDeclarator: {
        extends: 'Node',
        fields: [
          '@id',
          '@init',
          '@decltype',
          '@arguments'
        ]
      },
      Expression: {
        extends: 'Pattern'
      },
      ThisExpression: {
        extends: 'Expression'
      },
      ArrayExpression: {
        extends: 'Expression',
        fields: [
          '@elements'
        ]
      },
      ObjectExpression: {
        extends: 'Expression',
        fields: [
          '@properties'
        ]
      },
      Property: {
        extends: 'Node',
        fields: [
          '@key',
          '@value',
          'kind'
        ]
      },
      FunctionExpression: {
        extends: 'Expression',
        fields: [
          '@id',
          '@params',
          '@body',
          '@decltype',
          'generator',
          'expression'
        ]
      },
      SequenceExpression: {
        extends: 'Expression',
        fields: [
          '@expressions'
        ]
      },
      UnaryExpression: {
        extends: 'Expression',
        fields: [
          'operator',
          '@argument',
          'prefix'
        ]
      },
      BinaryExpression: {
        extends: 'Expression',
        fields: [
          'operator',
          '@left',
          '@right'
        ]
      },
      AssignmentExpression: {
        extends: 'Expression',
        fields: [
          '@left',
          'operator',
          '@right'
        ]
      },
      UpdateExpression: {
        extends: 'Expression',
        fields: [
          'operator',
          '@argument',
          'prefix'
        ]
      },
      LogicalExpression: {
        extends: 'Expression',
        fields: [
          'operator',
          '@left',
          '@right'
        ]
      },
      ConditionalExpression: {
        extends: 'Expression',
        fields: [
          '@test',
          '@consequent',
          '@alternate'
        ]
      },
      NewExpression: {
        extends: 'Expression',
        fields: [
          '@callee',
          '@arguments'
        ]
      },
      CallExpression: {
        extends: 'Expression',
        fields: [
          '@callee',
          '@arguments'
        ]
      },
      MemberExpression: {
        extends: 'Expression',
        fields: [
          '@object',
          '@property',
          'computed',
          'kind'
        ]
      },
      YieldExpression: {
        extends: 'Expression',
        fields: [
          '@argument'
        ]
      },
      ComprehensionExpression: {
        extends: 'Expression',
        fields: [
          '@blocks',
          '@filter'
        ]
      },
      GeneratorExpression: {
        extends: 'Expression',
        fields: [
          '@blocks',
          '@filter'
        ]
      },
      LetExpression: {
        extends: 'Expression',
        fields: [
          '@head',
          '@body'
        ]
      },
      Pattern: {
        extends: 'Node'
      },
      ObjectPattern: {
        extends: 'Pattern',
        fields: [
          '@properties'
        ]
      },
      ArrayPattern: {
        extends: 'Pattern',
        fields: [
          '@elements'
        ]
      },
      SwitchCase: {
        extends: 'Node',
        fields: [
          '@test',
          '@consequent'
        ]
      },
      CatchClause: {
        extends: 'Node',
        fields: [
          '@param',
          '@guard',
          '@body'
        ]
      },
      Identifier: {
        extends: 'Expression',
        fields: [
          'name',
          'kind'
        ]
      },
      Literal: {
        extends: 'Expression',
        fields: [
          'value'
        ]
      },
      Type: {
        extends: 'Node'
      },
      PointerType: {
        extends: 'Type',
        fields: [
          '@base'
        ]
      },
      ArrayType: {
        extends: 'PointerType',
        fields: [
          'length'
        ]
      },
      StructType: {
        extends: 'Type',
        fields: [
          '@id',
          '@members',
          'isUnion'
        ]
      },
      MemberDeclarator: {
        extends: 'Node',
        fields: [
          'modifiers',
          '@declarator'
        ]
      },
      ArrowType: {
        extends: 'Type',
        fields: [
          '@params',
          '@return'
        ]
      },
      TypeIdentifier: {
        extends: 'Type',
        fields: [
          'name'
        ]
      },
      TypeAliasDirective: {
        extends: 'Node',
        fields: [
          '@original',
          '@alias'
        ]
      },
      CastExpression: {
        extends: 'Expression',
        fields: [
          '@as',
          '@argument'
        ]
      }
    };
  function allFields(spec) {
    var fields = [
        'leadingComments',
        'loc'
      ];
    while (spec) {
      if (spec.fields) {
        fields = spec.fields.concat(fields);
      }
      spec = spec.extends ? lang[spec.extends] : null;
    }
    return fields;
  }
  ;
  exports.allFields = allFields;
  function prefixUnderscore(s) {
    return '_' + s;
  }
  function ensureConstructor(name, spec) {
    if (!exports[name]) {
      var fields = allFields(spec);
      var children = [];
      var body = [
          'this.type = "' + name + '";'
        ];
      for (var i = 0, j = fields.length; i < j; i++) {
        var fname = fields[i];
        if (fname.charAt(0) === '@') {
          fields[i] = fname = fname.substr(1);
          children.push(fname);
        }
        body.push('this.' + fname + ' = _' + fname + ';');
      }
      var node = new Function(fields.map(prefixUnderscore), body.join('\n'));
      if (spec.extends) {
        var pnode = ensureConstructor(spec.extends, lang[spec.extends]);
        node.prototype = Object.create(pnode.prototype);
      }
      Object.defineProperty(node.prototype, '_children', {
        value: children,
        writable: true,
        configurable: true,
        enumerable: false
      });
      exports[name] = node;
    }
    return exports[name];
  }
  for (var name in lang) {
    ensureConstructor(name, lang[name]);
  }
  exports.makePass = function makePass(name, prop) {
    return function (o) {
      var trans, arr;
      var child, children = this._children;
      for (var i = 0, j = children.length; i < j; i++) {
        if (!(child = this[children[i]])) {
          continue;
        }
        if (child instanceof Array) {
          arr = this[children[i]] = [];
          for (var k = 0, l = child.length; k < l; k++) {
            if (!child[k]) {
              arr.push(child[k]);
            } else if (typeof child[k][name] === 'function') {
              trans = child[k][name](o);
              if (trans !== null) {
                arr.push(trans);
              }
            }
          }
        } else if (typeof child[name] === 'function') {
          trans = child[name](o);
          if (trans === null) {
            this[children[i]] = undefined;
          } else {
            this[children[i]] = trans;
          }
        }
      }
      if (typeof this[prop] === 'function') {
        if (o.logger && typeof this.loc !== 'undefined') {
          o.logger.push(this);
          trans = this[prop](o);
          o.logger.pop();
        } else {
          trans = this[prop](o);
        }
        if (trans === null) {
          return null;
        }
        return trans ? trans : this;
      }
      return this;
    };
  };
  exports.makePass = function makePass(name, prop, backward) {
    return function (o) {
      var trans, arr;
      var child, children = this._children;
      var i, k;
      for (var x = 0, j = children.length; x < j; x++) {
        i = backward ? children.length - 1 - x : x;
        if (!(child = this[children[i]])) {
          continue;
        }
        if (child instanceof Array) {
          arr = this[children[i]] = [];
          var y;
          for (var y = 0, l = child.length; y < l; y++) {
            k = backward ? child.length - 1 - y : y;
            if (!child[k]) {
              if (backward) {
                arr.unshift(child[k]);
              } else {
                arr.push(child[k]);
              }
            } else if (typeof child[k][name] === 'function') {
              trans = child[k][name](o);
              if (trans !== null) {
                if (backward) {
                  arr.unshift(trans);
                } else {
                  arr.push(trans);
                }
              }
            }
          }
        } else if (typeof child[name] === 'function') {
          trans = child[name](o);
          if (trans === null) {
            this[children[i]] = undefined;
          } else {
            this[children[i]] = trans;
          }
        }
      }
      if (typeof this[prop] === 'function') {
        if (o.logger && typeof this.loc !== 'undefined') {
          o.logger.push(this);
          trans = this[prop](o);
          o.logger.pop();
        } else {
          trans = this[prop](o);
        }
        if (trans === null) {
          return null;
        }
        return trans ? trans : this;
      }
      return this;
    };
  };
  exports.lift = function lift(raw) {
    if (!raw) {
      return raw;
    }
    if (raw instanceof Array) {
      return raw.map(function (r) {
        return r ? lift(r) : r;
      });
    }
    var type = raw.type;
    var Node = exports[type];
    if (!Node) {
      throw new Error('unknown node type `' + type + '\'');
    }
    var node = new Node();
    node.loc = raw.loc;
    var fields = allFields(lang[type]);
    for (var i = 0, j = fields.length; i < j; i++) {
      var field;
      if (fields[i].charAt(0) === '@') {
        field = fields[i].substr(1);
        if (raw[field]) {
          node[field] = lift(raw[field]);
        }
      } else {
        field = fields[i];
        node[field] = raw[field];
      }
    }
    return node;
  };
  exports.flatten = function flatten(node) {
    if (!node) {
      return node;
    }
    if (node instanceof Array) {
      return node.map(function (n) {
        return flatten(n);
      });
    }
    var type = node.type;
    var raw = {
        type: type
      };
    var fields = allFields(lang[type]);
    for (var i = 0, j = fields.length; i < j; i++) {
      var field;
      if (fields[i].charAt(0) === '@') {
        field = fields[i].substr(1);
        if (node[field]) {
          raw[field] = flatten(node[field]);
        } else {
          raw[field] = null;
        }
      } else {
        field = fields[i];
        raw[field] = node[field];
      }
    }
    return raw;
  };
}(typeof exports === 'undefined' ? estransform = {} : exports));
(function (exports) {
  var Syntax, Precedence, BinaryPrecedence, Regex, VisitorKeys, VisitorOption, isArray, base, indent, json, renumber, hexadecimal, quotes, escapeless, newline, space, parentheses, semicolons, extra, parse;
  Syntax = {
    AssignmentExpression: 'AssignmentExpression',
    ArrayExpression: 'ArrayExpression',
    BlockStatement: 'BlockStatement',
    BinaryExpression: 'BinaryExpression',
    BreakStatement: 'BreakStatement',
    CallExpression: 'CallExpression',
    CatchClause: 'CatchClause',
    ConditionalExpression: 'ConditionalExpression',
    ContinueStatement: 'ContinueStatement',
    DoWhileStatement: 'DoWhileStatement',
    DebuggerStatement: 'DebuggerStatement',
    EmptyStatement: 'EmptyStatement',
    ExpressionStatement: 'ExpressionStatement',
    ForStatement: 'ForStatement',
    ForInStatement: 'ForInStatement',
    FunctionDeclaration: 'FunctionDeclaration',
    FunctionExpression: 'FunctionExpression',
    Identifier: 'Identifier',
    IfStatement: 'IfStatement',
    Literal: 'Literal',
    LabeledStatement: 'LabeledStatement',
    LogicalExpression: 'LogicalExpression',
    MemberExpression: 'MemberExpression',
    NewExpression: 'NewExpression',
    ObjectExpression: 'ObjectExpression',
    Program: 'Program',
    Property: 'Property',
    ReturnStatement: 'ReturnStatement',
    SequenceExpression: 'SequenceExpression',
    SwitchStatement: 'SwitchStatement',
    SwitchCase: 'SwitchCase',
    ThisExpression: 'ThisExpression',
    ThrowStatement: 'ThrowStatement',
    TryStatement: 'TryStatement',
    UnaryExpression: 'UnaryExpression',
    UpdateExpression: 'UpdateExpression',
    VariableDeclaration: 'VariableDeclaration',
    VariableDeclarator: 'VariableDeclarator',
    WhileStatement: 'WhileStatement',
    WithStatement: 'WithStatement'
  };
  Precedence = {
    Sequence: 0,
    Assignment: 1,
    Conditional: 2,
    LogicalOR: 3,
    LogicalAND: 4,
    BitwiseOR: 5,
    BitwiseXOR: 6,
    BitwiseAND: 7,
    Equality: 8,
    Relational: 9,
    BitwiseSHIFT: 10,
    Additive: 11,
    Multiplicative: 12,
    Unary: 13,
    Postfix: 14,
    Call: 15,
    New: 16,
    Member: 17,
    Primary: 18
  };
  BinaryPrecedence = {
    '||': Precedence.LogicalOR,
    '&&': Precedence.LogicalAND,
    '|': Precedence.BitwiseOR,
    '^': Precedence.BitwiseXOR,
    '&': Precedence.BitwiseAND,
    '==': Precedence.Equality,
    '!=': Precedence.Equality,
    '===': Precedence.Equality,
    '!==': Precedence.Equality,
    '<': Precedence.Relational,
    '>': Precedence.Relational,
    '<=': Precedence.Relational,
    '>=': Precedence.Relational,
    'in': Precedence.Relational,
    'instanceof': Precedence.Relational,
    '<<': Precedence.BitwiseSHIFT,
    '>>': Precedence.BitwiseSHIFT,
    '>>>': Precedence.BitwiseSHIFT,
    '+': Precedence.Additive,
    '-': Precedence.Additive,
    '*': Precedence.Multiplicative,
    '%': Precedence.Multiplicative,
    '/': Precedence.Multiplicative
  };
  Regex = {
    NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]')
  };
  function getDefaultOptions() {
    return {
      indent: null,
      base: null,
      parse: null,
      comment: false,
      format: {
        indent: {
          style: '    ',
          base: 0,
          adjustMultilineComment: false
        },
        json: false,
        renumber: false,
        hexadecimal: false,
        quotes: 'single',
        escapeless: false,
        compact: false,
        parentheses: true,
        semicolons: true
      }
    };
  }
  function stringToArray(str) {
    var length = str.length, result = [], i;
    for (i = 0; i < length; i += 1) {
      result[i] = str.charAt(i);
    }
    return result;
  }
  function stringRepeat(str, num) {
    var result = '';
    for (num |= 0; num > 0; num >>>= 1, str += str) {
      if (num & 1) {
        result += str;
      }
    }
    return result;
  }
  isArray = Array.isArray;
  if (!isArray) {
    isArray = function isArray(array) {
      return Object.prototype.toString.call(array) === '[object Array]';
    };
  }
  function endsWithLineTerminator(str) {
    var len, ch;
    len = str.length;
    ch = str.charAt(len - 1);
    return ch === '\r' || ch === '\n';
  }
  function shallowCopy(obj) {
    var ret = {}, key;
    for (key in obj) {
      if (obj.hasOwnProperty(key)) {
        ret[key] = obj[key];
      }
    }
    return ret;
  }
  function deepCopy(obj) {
    var ret = {}, key, val;
    for (key in obj) {
      if (obj.hasOwnProperty(key)) {
        val = obj[key];
        if (typeof val === 'object' && val !== null) {
          ret[key] = deepCopy(val);
        } else {
          ret[key] = val;
        }
      }
    }
    return ret;
  }
  function updateDeeply(target, override) {
    var key, val;
    function isHashObject(target) {
      return typeof target === 'object' && target instanceof Object && !(target instanceof RegExp);
    }
    for (key in override) {
      if (override.hasOwnProperty(key)) {
        val = override[key];
        if (isHashObject(val)) {
          if (isHashObject(target[key])) {
            updateDeeply(target[key], val);
          } else {
            target[key] = updateDeeply({}, val);
          }
        } else {
          target[key] = val;
        }
      }
    }
    return target;
  }
  function generateNumber(value) {
    var result, point, temp, exponent, pos;
    if (value !== value) {
      throw new Error('Numeric literal whose value is NaN');
    }
    if (1 / value < 0) {
      throw new Error('Numeric literal whose value is negative');
    }
    if (value === 1 / 0) {
      return json ? 'null' : renumber ? '1e400' : '1e+400';
    }
    result = '' + value;
    if (!renumber || result.length < 3) {
      return result;
    }
    point = result.indexOf('.');
    if (!json && result.charAt(0) === '0' && point === 1) {
      point = 0;
      result = result.slice(1);
    }
    temp = result;
    result = result.replace('e+', 'e');
    exponent = 0;
    if ((pos = temp.indexOf('e')) > 0) {
      exponent = +temp.slice(pos + 1);
      temp = temp.slice(0, pos);
    }
    if (point >= 0) {
      exponent -= temp.length - point - 1;
      temp = +(temp.slice(0, point) + temp.slice(point + 1)) + '';
    }
    pos = 0;
    while (temp.charAt(temp.length + pos - 1) === '0') {
      pos -= 1;
    }
    if (pos !== 0) {
      exponent -= pos;
      temp = temp.slice(0, pos);
    }
    if (exponent !== 0) {
      temp += 'e' + exponent;
    }
    if ((temp.length < result.length || hexadecimal && value > 1000000000000 && Math.floor(value) === value && (temp = '0x' + value.toString(16)).length < result.length) && +temp === value) {
      result = temp;
    }
    return result;
  }
  function escapeAllowedCharacter(ch, next) {
    var code = ch.charCodeAt(0), hex = code.toString(16), result = '\\';
    switch (ch) {
    case '\b':
      result += 'b';
      break;
    case '\f':
      result += 'f';
      break;
    case '\t':
      result += 't';
      break;
    default:
      if (json || code > 255) {
        result += 'u' + '0000'.slice(hex.length) + hex;
      } else if (ch === '\0' && '0123456789'.indexOf(next) < 0) {
        result += '0';
      } else if (ch === '\v') {
        result += 'v';
      } else {
        result += 'x' + '00'.slice(hex.length) + hex;
      }
      break;
    }
    return result;
  }
  function escapeDisallowedCharacter(ch) {
    var result = '\\';
    switch (ch) {
    case '\\':
      result += '\\';
      break;
    case '\n':
      result += 'n';
      break;
    case '\r':
      result += 'r';
      break;
    case '\u2028':
      result += 'u2028';
      break;
    case '\u2029':
      result += 'u2029';
      break;
    default:
      throw new Error('Incorrectly classified character');
    }
    return result;
  }
  function escapeString(str) {
    var result = '', i, len, ch, next, singleQuotes = 0, doubleQuotes = 0, single;
    if (typeof str[0] === 'undefined') {
      str = stringToArray(str);
    }
    for (i = 0, len = str.length; i < len; i += 1) {
      ch = str[i];
      if (ch === '\'') {
        singleQuotes += 1;
      } else if (ch === '"') {
        doubleQuotes += 1;
      } else if (ch === '/' && json) {
        result += '\\';
      } else if ('\\\n\r\u2028\u2029'.indexOf(ch) >= 0) {
        result += escapeDisallowedCharacter(ch);
        continue;
      } else if (json && ch < ' ' || !(json || escapeless || ch >= ' ' && ch <= '~')) {
        result += escapeAllowedCharacter(ch, str[i + 1]);
        continue;
      }
      result += ch;
    }
    single = !(quotes === 'double' || quotes === 'auto' && doubleQuotes < singleQuotes);
    str = result;
    result = single ? '\'' : '"';
    if (typeof str[0] === 'undefined') {
      str = stringToArray(str);
    }
    for (i = 0, len = str.length; i < len; i += 1) {
      ch = str[i];
      if (ch === '\'' && single || ch === '"' && !single) {
        result += '\\';
      }
      result += ch;
    }
    return result + (single ? '\'' : '"');
  }
  function isWhiteSpace(ch) {
    return '\t\v\f \xa0'.indexOf(ch) >= 0 || ch.charCodeAt(0) >= 5760 && '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\ufeff'.indexOf(ch) >= 0;
  }
  function isLineTerminator(ch) {
    return '\n\r\u2028\u2029'.indexOf(ch) >= 0;
  }
  function isIdentifierPart(ch) {
    return ch === '$' || ch === '_' || ch === '\\' || ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9' || ch.charCodeAt(0) >= 128 && Regex.NonAsciiIdentifierPart.test(ch);
  }
  function join(left, right) {
    var leftChar = left.charAt(left.length - 1), rightChar = right.charAt(0);
    if ((leftChar === '+' || leftChar === '-') && leftChar === rightChar || isIdentifierPart(leftChar) && isIdentifierPart(rightChar)) {
      return left + ' ' + right;
    } else if (isWhiteSpace(leftChar) || isLineTerminator(leftChar) || isWhiteSpace(rightChar) || isLineTerminator(rightChar)) {
      return left + right;
    }
    return left + space + right;
  }
  function addIndent(stmt) {
    return base + stmt;
  }
  function calculateSpaces(str) {
    var i;
    for (i = str.length - 1; i >= 0; i -= 1) {
      if (isLineTerminator(str.charAt(i))) {
        break;
      }
    }
    return str.length - 1 - i;
  }
  function adjustMultilineComment(value, specialBase) {
    var array, i, len, line, j, ch, spaces, previousBase;
    array = value.split(/\r\n|[\r\n]/);
    spaces = Number.MAX_VALUE;
    for (i = 1, len = array.length; i < len; i += 1) {
      line = array[i];
      j = 0;
      while (j < line.length && isWhiteSpace(line[j])) {
        j += 1;
      }
      if (spaces > j) {
        spaces = j;
      }
    }
    if (typeof specialBase !== 'undefined') {
      previousBase = base;
      if (array[1][spaces] === '*') {
        specialBase += ' ';
      }
      base = specialBase;
    } else {
      if (spaces % 2 === 1) {
        spaces -= 1;
      }
      previousBase = base;
    }
    for (i = 1, len = array.length; i < len; i += 1) {
      array[i] = addIndent(array[i].slice(spaces));
    }
    base = previousBase;
    return array.join('\n');
  }
  function generateComment(comment, specialBase) {
    if (comment.type === 'Line') {
      if (endsWithLineTerminator(comment.value)) {
        return '//' + comment.value;
      } else {
        return '//' + comment.value + '\n';
      }
    }
    if (extra.format.indent.adjustMultilineComment && /[\n\r]/.test(comment.value)) {
      return adjustMultilineComment('/*' + comment.value + '*/', specialBase);
    }
    return '/*' + comment.value + '*/';
  }
  function addCommentsToStatement(stmt, result) {
    var i, len, comment, save, node, tailingToStatement, specialBase, fragment;
    if (stmt.leadingComments) {
      save = result;
      comment = stmt.leadingComments[0];
      result = generateComment(comment);
      if (!endsWithLineTerminator(result)) {
        result += '\n';
      }
      for (i = 1, len = stmt.leadingComments.length; i < len; i += 1) {
        comment = stmt.leadingComments[i];
        fragment = generateComment(comment);
        if (!endsWithLineTerminator(fragment)) {
          fragment += '\n';
        }
        result += addIndent(fragment);
      }
      result += addIndent(save);
    }
    if (stmt.trailingComments) {
      tailingToStatement = !endsWithLineTerminator(result);
      specialBase = stringRepeat(' ', calculateSpaces(base + result + indent));
      for (i = 0, len = stmt.trailingComments.length; i < len; i += 1) {
        comment = stmt.trailingComments[i];
        if (tailingToStatement) {
          if (i === 0) {
            result += indent;
          } else {
            result += specialBase;
          }
          result += generateComment(comment, specialBase);
        } else {
          result += addIndent(generateComment(comment));
        }
        if (i !== len - 1 && !endsWithLineTerminator(result)) {
          result += '\n';
        }
      }
    }
    return result;
  }
  function parenthesize(text, current, should) {
    if (current < should) {
      return '(' + text + ')';
    }
    return text;
  }
  function maybeBlock(stmt, semicolonOptional) {
    var previousBase, result, noLeadingComment;
    noLeadingComment = !extra.comment || !stmt.leadingComments;
    if (stmt.type === Syntax.BlockStatement && noLeadingComment) {
      return space + generateStatement(stmt);
    }
    if (stmt.type === Syntax.EmptyStatement && noLeadingComment) {
      return ';';
    }
    previousBase = base;
    base += indent;
    result = newline + addIndent(generateStatement(stmt, {
      semicolonOptional: semicolonOptional
    }));
    base = previousBase;
    return result;
  }
  function maybeBlockSuffix(stmt, result) {
    if (stmt.type === Syntax.BlockStatement && (!extra.comment || !stmt.leadingComments) && !endsWithLineTerminator(result)) {
      return space;
    }
    if (endsWithLineTerminator(result)) {
      return addIndent('');
    }
    return (newline === '' ? ' ' : newline) + addIndent('');
  }
  function generateFunctionBody(node) {
    var result, i, len;
    result = '(';
    for (i = 0, len = node.params.length; i < len; i += 1) {
      result += node.params[i].name;
      if (i + 1 < len) {
        result += ',' + space;
      }
    }
    return result + ')' + maybeBlock(node.body);
  }
  function generateExpression(expr, option) {
    var result, precedence, currentPrecedence, previousBase, i, len, raw, fragment, allowIn, allowCall, allowUnparenthesizedNew;
    precedence = option.precedence;
    allowIn = option.allowIn;
    allowCall = option.allowCall;
    switch (expr.type) {
    case Syntax.SequenceExpression:
      result = '';
      allowIn |= Precedence.Sequence < precedence;
      for (i = 0, len = expr.expressions.length; i < len; i += 1) {
        result += generateExpression(expr.expressions[i], {
          precedence: Precedence.Assignment,
          allowIn: allowIn,
          allowCall: true
        });
        if (i + 1 < len) {
          result += ',' + space;
        }
      }
      result = parenthesize(result, Precedence.Sequence, precedence);
      break;
    case Syntax.AssignmentExpression:
      allowIn |= Precedence.Assignment < precedence;
      result = parenthesize(generateExpression(expr.left, {
        precedence: Precedence.Call,
        allowIn: allowIn,
        allowCall: true
      }) + space + expr.operator + space + generateExpression(expr.right, {
        precedence: Precedence.Assignment,
        allowIn: allowIn,
        allowCall: true
      }), Precedence.Assignment, precedence);
      break;
    case Syntax.ConditionalExpression:
      allowIn |= Precedence.Conditional < precedence;
      result = parenthesize(generateExpression(expr.test, {
        precedence: Precedence.LogicalOR,
        allowIn: allowIn,
        allowCall: true
      }) + space + '?' + space + generateExpression(expr.consequent, {
        precedence: Precedence.Assignment,
        allowIn: allowIn,
        allowCall: true
      }) + space + ':' + space + generateExpression(expr.alternate, {
        precedence: Precedence.Assignment,
        allowIn: allowIn,
        allowCall: true
      }), Precedence.Conditional, precedence);
      break;
    case Syntax.LogicalExpression:
    case Syntax.BinaryExpression:
      currentPrecedence = BinaryPrecedence[expr.operator];
      allowIn |= currentPrecedence < precedence;
      result = join(generateExpression(expr.left, {
        precedence: currentPrecedence,
        allowIn: allowIn,
        allowCall: true
      }), expr.operator);
      fragment = generateExpression(expr.right, {
        precedence: currentPrecedence + 1,
        allowIn: allowIn,
        allowCall: true
      });
      if (expr.operator === '/' && result.charAt(result.length - 1) === '/') {
        result += ' ' + fragment;
      } else {
        result = join(result, fragment);
      }
      if (expr.operator === 'in' && !allowIn) {
        result = '(' + result + ')';
      } else {
        result = parenthesize(result, currentPrecedence, precedence);
      }
      break;
    case Syntax.CallExpression:
      result = generateExpression(expr.callee, {
        precedence: Precedence.Call,
        allowIn: true,
        allowCall: true,
        allowUnparenthesizedNew: false
      });
      result += '(';
      for (i = 0, len = expr['arguments'].length; i < len; i += 1) {
        result += generateExpression(expr['arguments'][i], {
          precedence: Precedence.Assignment,
          allowIn: true,
          allowCall: true
        });
        if (i + 1 < len) {
          result += ',' + space;
        }
      }
      result += ')';
      if (!allowCall) {
        result = '(' + result + ')';
      } else {
        result = parenthesize(result, Precedence.Call, precedence);
      }
      break;
    case Syntax.NewExpression:
      len = expr['arguments'].length;
      allowUnparenthesizedNew = option.allowUnparenthesizedNew === undefined || option.allowUnparenthesizedNew;
      result = join('new', generateExpression(expr.callee, {
        precedence: Precedence.New,
        allowIn: true,
        allowCall: false,
        allowUnparenthesizedNew: allowUnparenthesizedNew && !parentheses && len === 0
      }));
      if (!allowUnparenthesizedNew || parentheses || len > 0) {
        result += '(';
        for (i = 0; i < len; i += 1) {
          result += generateExpression(expr['arguments'][i], {
            precedence: Precedence.Assignment,
            allowIn: true,
            allowCall: true
          });
          if (i + 1 < len) {
            result += ',' + space;
          }
        }
        result += ')';
      }
      result = parenthesize(result, Precedence.New, precedence);
      break;
    case Syntax.MemberExpression:
      result = generateExpression(expr.object, {
        precedence: Precedence.Call,
        allowIn: true,
        allowCall: allowCall,
        allowUnparenthesizedNew: false
      });
      if (expr.computed) {
        result += '[' + generateExpression(expr.property, {
          precedence: Precedence.Sequence,
          allowIn: true,
          allowCall: allowCall
        }) + ']';
      } else {
        if (expr.object.type === Syntax.Literal && typeof expr.object.value === 'number') {
          if (result.indexOf('.') < 0) {
            if (!/[eExX]/.test(result) && !(result.length >= 2 && result[0] === '0')) {
              result += '.';
            }
          }
        }
        result += '.' + expr.property.name;
      }
      result = parenthesize(result, Precedence.Member, precedence);
      break;
    case Syntax.UnaryExpression:
      fragment = generateExpression(expr.argument, {
        precedence: Precedence.Unary + (expr.argument.type === Syntax.UnaryExpression && expr.operator.length < 3 && expr.argument.operator === expr.operator ? 1 : 0),
        allowIn: true,
        allowCall: true
      });
      if (space === '') {
        result = join(expr.operator, fragment);
      } else {
        result = expr.operator;
        if (result.length > 2) {
          result += ' ';
        }
        result += fragment;
      }
      result = parenthesize(result, Precedence.Unary, precedence);
      break;
    case Syntax.UpdateExpression:
      if (expr.prefix) {
        result = parenthesize(expr.operator + generateExpression(expr.argument, {
          precedence: Precedence.Unary,
          allowIn: true,
          allowCall: true
        }), Precedence.Unary, precedence);
      } else {
        result = parenthesize(generateExpression(expr.argument, {
          precedence: Precedence.Postfix,
          allowIn: true,
          allowCall: true
        }) + expr.operator, Precedence.Postfix, precedence);
      }
      break;
    case Syntax.FunctionExpression:
      result = 'function';
      if (expr.id) {
        result += ' ' + expr.id.name;
      } else {
        result += space;
      }
      result += generateFunctionBody(expr);
      break;
    case Syntax.ArrayExpression:
      if (!expr.elements.length) {
        result = '[]';
        break;
      }
      result = '[' + newline;
      previousBase = base;
      base += indent;
      for (i = 0, len = expr.elements.length; i < len; i += 1) {
        if (!expr.elements[i]) {
          result += addIndent('');
          if (i + 1 === len) {
            result += ',';
          }
        } else {
          result += addIndent(generateExpression(expr.elements[i], {
            precedence: Precedence.Assignment,
            allowIn: true,
            allowCall: true
          }));
        }
        if (i + 1 < len) {
          result += ',' + newline;
        }
      }
      base = previousBase;
      if (!endsWithLineTerminator(result)) {
        result += newline;
      }
      result += addIndent(']');
      break;
    case Syntax.Property:
      if (expr.kind === 'get' || expr.kind === 'set') {
        result = expr.kind + ' ' + generateExpression(expr.key, {
          precedence: Precedence.Sequence,
          allowIn: true,
          allowCall: true
        }) + generateFunctionBody(expr.value);
      } else {
        result = generateExpression(expr.key, {
          precedence: Precedence.Sequence,
          allowIn: true,
          allowCall: true
        }) + ':' + space + generateExpression(expr.value, {
          precedence: Precedence.Assignment,
          allowIn: true,
          allowCall: true
        });
      }
      break;
    case Syntax.ObjectExpression:
      if (!expr.properties.length) {
        result = '{}';
        break;
      }
      result = '{' + newline;
      previousBase = base;
      base += indent;
      for (i = 0, len = expr.properties.length; i < len; i += 1) {
        result += addIndent(generateExpression(expr.properties[i], {
          precedence: Precedence.Sequence,
          allowIn: true,
          allowCall: true
        }));
        if (i + 1 < len) {
          result += ',' + newline;
        }
      }
      base = previousBase;
      if (!endsWithLineTerminator(result)) {
        result += newline;
      }
      result += addIndent('}');
      break;
    case Syntax.ThisExpression:
      result = 'this';
      break;
    case Syntax.Identifier:
      result = expr.name;
      break;
    case Syntax.Literal:
      if (expr.hasOwnProperty('raw') && parse) {
        try {
          raw = parse(expr.raw).body[0].expression;
          if (raw.type === Syntax.Literal) {
            if (raw.value === expr.value) {
              result = expr.raw;
              break;
            }
          }
        } catch (e) {
        }
      }
      if (expr.value === null) {
        result = 'null';
        break;
      }
      if (typeof expr.value === 'string') {
        result = escapeString(expr.value);
        break;
      }
      if (typeof expr.value === 'number') {
        result = generateNumber(expr.value);
        break;
      }
      result = expr.value.toString();
      break;
    default:
      break;
    }
    if (result === undefined) {
      throw new Error('Unknown expression type: ' + expr.type);
    }
    return result;
  }
  function generateStatement(stmt, option) {
    var i, len, result, previousBase, node, allowIn, fragment, semicolon;
    allowIn = true;
    semicolon = ';';
    if (option) {
      allowIn = option.allowIn === undefined || option.allowIn;
      if (!semicolons && option.semicolonOptional === true) {
        semicolon = '';
      }
    }
    switch (stmt.type) {
    case Syntax.BlockStatement:
      result = '{' + newline;
      previousBase = base;
      base += indent;
      for (i = 0, len = stmt.body.length; i < len; i += 1) {
        fragment = addIndent(generateStatement(stmt.body[i], {
          semicolonOptional: i === len - 1
        }));
        result += fragment;
        if (!endsWithLineTerminator(fragment)) {
          result += newline;
        }
      }
      base = previousBase;
      result += addIndent('}');
      break;
    case Syntax.BreakStatement:
      if (stmt.label) {
        result = 'break ' + stmt.label.name + semicolon;
      } else {
        result = 'break' + semicolon;
      }
      break;
    case Syntax.ContinueStatement:
      if (stmt.label) {
        result = 'continue ' + stmt.label.name + semicolon;
      } else {
        result = 'continue' + semicolon;
      }
      break;
    case Syntax.DoWhileStatement:
      result = join('do', maybeBlock(stmt.body));
      result += maybeBlockSuffix(stmt.body, result);
      result += 'while' + space + '(' + generateExpression(stmt.test, {
        precedence: Precedence.Sequence,
        allowIn: true,
        allowCall: true
      }) + ')' + semicolon;
      break;
    case Syntax.CatchClause:
      previousBase = base;
      base += indent;
      result = 'catch' + space + '(' + generateExpression(stmt.param, {
        precedence: Precedence.Sequence,
        allowIn: true,
        allowCall: true
      }) + ')';
      base = previousBase;
      result += maybeBlock(stmt.body);
      break;
    case Syntax.DebuggerStatement:
      result = 'debugger' + semicolon;
      break;
    case Syntax.EmptyStatement:
      result = ';';
      break;
    case Syntax.ExpressionStatement:
      result = generateExpression(stmt.expression, {
        precedence: Precedence.Sequence,
        allowIn: true,
        allowCall: true
      });
      if (result.charAt(0) === '{' || result.slice(0, 8) === 'function' && ' ('.indexOf(result.charAt(8)) >= 0) {
        result = '(' + result + ')' + semicolon;
      } else {
        result += semicolon;
      }
      break;
    case Syntax.VariableDeclarator:
      if (stmt.init) {
        result = stmt.id.name + space + '=' + space + generateExpression(stmt.init, {
          precedence: Precedence.Assignment,
          allowIn: allowIn,
          allowCall: true
        });
      } else {
        result = stmt.id.name;
      }
      break;
    case Syntax.VariableDeclaration:
      result = stmt.kind;
      if (stmt.declarations.length === 1 && stmt.declarations[0].init && stmt.declarations[0].init.type === Syntax.FunctionExpression) {
        result += ' ' + generateStatement(stmt.declarations[0], {
          allowIn: allowIn
        });
      } else {
        previousBase = base;
        base += indent;
        node = stmt.declarations[0];
        if (extra.comment && node.leadingComments) {
          result += '\n' + addIndent(generateStatement(node, {
            allowIn: allowIn
          }));
        } else {
          result += ' ' + generateStatement(node, {
            allowIn: allowIn
          });
        }
        for (i = 1, len = stmt.declarations.length; i < len; i += 1) {
          node = stmt.declarations[i];
          if (extra.comment && node.leadingComments) {
            result += ',' + newline + addIndent(generateStatement(node, {
              allowIn: allowIn
            }));
          } else {
            result += ',' + space + generateStatement(node, {
              allowIn: allowIn
            });
          }
        }
        base = previousBase;
      }
      result += semicolon;
      break;
    case Syntax.ThrowStatement:
      result = join('throw', generateExpression(stmt.argument, {
        precedence: Precedence.Sequence,
        allowIn: true,
        allowCall: true
      })) + semicolon;
      break;
    case Syntax.TryStatement:
      result = 'try' + maybeBlock(stmt.block);
      result += maybeBlockSuffix(stmt.block, result);
      for (i = 0, len = stmt.handlers.length; i < len; i += 1) {
        result += generateStatement(stmt.handlers[i]);
        if (stmt.finalizer || i + 1 !== len) {
          result += maybeBlockSuffix(stmt.handlers[i].body, result);
        }
      }
      if (stmt.finalizer) {
        result += 'finally' + maybeBlock(stmt.finalizer);
      }
      break;
    case Syntax.SwitchStatement:
      previousBase = base;
      base += indent;
      result = 'switch' + space + '(' + generateExpression(stmt.discriminant, {
        precedence: Precedence.Sequence,
        allowIn: true,
        allowCall: true
      }) + ')' + space + '{' + newline;
      base = previousBase;
      if (stmt.cases) {
        for (i = 0, len = stmt.cases.length; i < len; i += 1) {
          fragment = addIndent(generateStatement(stmt.cases[i], {
            semicolonOptional: i === len - 1
          }));
          result += fragment;
          if (!endsWithLineTerminator(fragment)) {
            result += newline;
          }
        }
      }
      result += addIndent('}');
      break;
    case Syntax.SwitchCase:
      previousBase = base;
      base += indent;
      if (stmt.test) {
        result = join('case', generateExpression(stmt.test, {
          precedence: Precedence.Sequence,
          allowIn: true,
          allowCall: true
        })) + ':';
      } else {
        result = 'default:';
      }
      i = 0;
      len = stmt.consequent.length;
      if (len && stmt.consequent[0].type === Syntax.BlockStatement) {
        fragment = maybeBlock(stmt.consequent[0]);
        result += fragment;
        i = 1;
      }
      if (i !== len && !endsWithLineTerminator(result)) {
        result += newline;
      }
      for (; i < len; i += 1) {
        fragment = addIndent(generateStatement(stmt.consequent[i], {
          semicolonOptional: i === len - 1 && semicolon === ''
        }));
        result += fragment;
        if (i + 1 !== len && !endsWithLineTerminator(fragment)) {
          result += newline;
        }
      }
      base = previousBase;
      break;
    case Syntax.IfStatement:
      previousBase = base;
      base += indent;
      if (stmt.alternate) {
        if (stmt.alternate.type === Syntax.IfStatement) {
          result = 'if' + space + '(' + generateExpression(stmt.test, {
            precedence: Precedence.Sequence,
            allowIn: true,
            allowCall: true
          }) + ')';
          base = previousBase;
          result += maybeBlock(stmt.consequent);
          result += maybeBlockSuffix(stmt.consequent, result);
          result += 'else ' + generateStatement(stmt.alternate);
        } else {
          result = 'if' + space + '(' + generateExpression(stmt.test, {
            precedence: Precedence.Sequence,
            allowIn: true,
            allowCall: true
          }) + ')';
          base = previousBase;
          result += maybeBlock(stmt.consequent);
          result += maybeBlockSuffix(stmt.consequent, result);
          result += 'else';
          result = join(result, maybeBlock(stmt.alternate, semicolon === ''));
        }
      } else {
        result = 'if' + space + '(' + generateExpression(stmt.test, {
          precedence: Precedence.Sequence,
          allowIn: true,
          allowCall: true
        }) + ')';
        base = previousBase;
        result += maybeBlock(stmt.consequent, semicolon === '');
      }
      break;
    case Syntax.ForStatement:
      previousBase = base;
      base += indent;
      result = 'for' + space + '(';
      if (stmt.init) {
        if (stmt.init.type === Syntax.VariableDeclaration) {
          result += generateStatement(stmt.init, {
            allowIn: false
          });
        } else {
          result += generateExpression(stmt.init, {
            precedence: Precedence.Sequence,
            allowIn: false,
            allowCall: true
          }) + ';';
        }
      } else {
        result += ';';
      }
      if (stmt.test) {
        result += space + generateExpression(stmt.test, {
          precedence: Precedence.Sequence,
          allowIn: true,
          allowCall: true
        }) + ';';
      } else {
        result += ';';
      }
      if (stmt.update) {
        result += space + generateExpression(stmt.update, {
          precedence: Precedence.Sequence,
          allowIn: true,
          allowCall: true
        }) + ')';
      } else {
        result += ')';
      }
      base = previousBase;
      result += maybeBlock(stmt.body, semicolon === '');
      break;
    case Syntax.ForInStatement:
      result = 'for' + space + '(';
      if (stmt.left.type === Syntax.VariableDeclaration) {
        previousBase = base;
        base += indent + indent;
        result += stmt.left.kind + ' ' + generateStatement(stmt.left.declarations[0], {
          allowIn: false
        });
        base = previousBase;
      } else {
        previousBase = base;
        base += indent;
        result += generateExpression(stmt.left, {
          precedence: Precedence.Call,
          allowIn: true,
          allowCall: true
        });
        base = previousBase;
      }
      previousBase = base;
      base += indent;
      result = join(result, 'in');
      result = join(result, generateExpression(stmt.right, {
        precedence: Precedence.Sequence,
        allowIn: true,
        allowCall: true
      })) + ')';
      base = previousBase;
      result += maybeBlock(stmt.body, semicolon === '');
      break;
    case Syntax.LabeledStatement:
      result = stmt.label.name + ':' + maybeBlock(stmt.body, semicolon === '');
      break;
    case Syntax.Program:
      result = '';
      for (i = 0, len = stmt.body.length; i < len; i += 1) {
        fragment = addIndent(generateStatement(stmt.body[i], {
          semicolonOptional: i === len - 1
        }));
        result += fragment;
        if (i + 1 < len && !endsWithLineTerminator(fragment)) {
          result += newline;
        }
      }
      break;
    case Syntax.FunctionDeclaration:
      result = 'function' + space;
      if (stmt.id) {
        result += (space === '' ? ' ' : '') + stmt.id.name;
      }
      result += generateFunctionBody(stmt);
      break;
    case Syntax.ReturnStatement:
      if (stmt.argument) {
        result = join('return', generateExpression(stmt.argument, {
          precedence: Precedence.Sequence,
          allowIn: true,
          allowCall: true
        })) + semicolon;
      } else {
        result = 'return' + semicolon;
      }
      break;
    case Syntax.WhileStatement:
      previousBase = base;
      base += indent;
      result = 'while' + space + '(' + generateExpression(stmt.test, {
        precedence: Precedence.Sequence,
        allowIn: true,
        allowCall: true
      }) + ')';
      base = previousBase;
      result += maybeBlock(stmt.body, semicolon === '');
      break;
    case Syntax.WithStatement:
      previousBase = base;
      base += indent;
      result = 'with' + space + '(' + generateExpression(stmt.object, {
        precedence: Precedence.Sequence,
        allowIn: true,
        allowCall: true
      }) + ')';
      base = previousBase;
      result += maybeBlock(stmt.body, semicolon === '');
      break;
    default:
      break;
    }
    if (result === undefined) {
      throw new Error('Unknown statement type: ' + stmt.type);
    }
    if (extra.comment) {
      return addCommentsToStatement(stmt, result);
    }
    return result;
  }
  function generate(node, options) {
    var defaultOptions = getDefaultOptions();
    if (typeof options !== 'undefined') {
      if (typeof options.indent === 'string') {
        defaultOptions.format.indent.style = options.indent;
      }
      if (typeof options.base === 'number') {
        defaultOptions.format.indent.base = options.base;
      }
      options = updateDeeply(defaultOptions, options);
      indent = options.format.indent.style;
      if (typeof options.base === 'string') {
        base = options.base;
      } else {
        base = stringRepeat(indent, options.format.indent.base);
      }
    } else {
      options = defaultOptions;
      indent = options.format.indent.style;
      base = stringRepeat(indent, options.format.indent.base);
    }
    json = options.format.json;
    renumber = options.format.renumber;
    hexadecimal = json ? false : options.format.hexadecimal;
    quotes = json ? 'double' : options.format.quotes;
    escapeless = options.format.escapeless;
    if (options.format.compact) {
      newline = space = indent = base = '';
    } else {
      newline = '\n';
      space = ' ';
    }
    parentheses = options.format.parentheses;
    semicolons = options.format.semicolons;
    parse = json ? null : options.parse;
    extra = options;
    switch (node.type) {
    case Syntax.BlockStatement:
    case Syntax.BreakStatement:
    case Syntax.CatchClause:
    case Syntax.ContinueStatement:
    case Syntax.DoWhileStatement:
    case Syntax.DebuggerStatement:
    case Syntax.EmptyStatement:
    case Syntax.ExpressionStatement:
    case Syntax.ForStatement:
    case Syntax.ForInStatement:
    case Syntax.FunctionDeclaration:
    case Syntax.IfStatement:
    case Syntax.LabeledStatement:
    case Syntax.Program:
    case Syntax.ReturnStatement:
    case Syntax.SwitchStatement:
    case Syntax.SwitchCase:
    case Syntax.ThrowStatement:
    case Syntax.TryStatement:
    case Syntax.VariableDeclaration:
    case Syntax.VariableDeclarator:
    case Syntax.WhileStatement:
    case Syntax.WithStatement:
      return generateStatement(node);
    case Syntax.AssignmentExpression:
    case Syntax.ArrayExpression:
    case Syntax.BinaryExpression:
    case Syntax.CallExpression:
    case Syntax.ConditionalExpression:
    case Syntax.FunctionExpression:
    case Syntax.Identifier:
    case Syntax.Literal:
    case Syntax.LogicalExpression:
    case Syntax.MemberExpression:
    case Syntax.NewExpression:
    case Syntax.ObjectExpression:
    case Syntax.Property:
    case Syntax.SequenceExpression:
    case Syntax.ThisExpression:
    case Syntax.UnaryExpression:
    case Syntax.UpdateExpression:
      return generateExpression(node, {
        precedence: Precedence.Sequence,
        allowIn: true,
        allowCall: true
      });
    default:
      break;
    }
    throw new Error('Unknown node type: ' + node.type);
  }
  VisitorKeys = {
    AssignmentExpression: [
      'left',
      'right'
    ],
    ArrayExpression: [
      'elements'
    ],
    BlockStatement: [
      'body'
    ],
    BinaryExpression: [
      'left',
      'right'
    ],
    BreakStatement: [
      'label'
    ],
    CallExpression: [
      'callee',
      'arguments'
    ],
    CatchClause: [
      'param',
      'body'
    ],
    ConditionalExpression: [
      'test',
      'consequent',
      'alternate'
    ],
    ContinueStatement: [
      'label'
    ],
    DoWhileStatement: [
      'body',
      'test'
    ],
    DebuggerStatement: [],
    EmptyStatement: [],
    ExpressionStatement: [
      'expression'
    ],
    ForStatement: [
      'init',
      'test',
      'update',
      'body'
    ],
    ForInStatement: [
      'left',
      'right',
      'body'
    ],
    FunctionDeclaration: [
      'id',
      'params',
      'body'
    ],
    FunctionExpression: [
      'id',
      'params',
      'body'
    ],
    Identifier: [],
    IfStatement: [
      'test',
      'consequent',
      'alternate'
    ],
    Literal: [],
    LabeledStatement: [
      'label',
      'body'
    ],
    LogicalExpression: [
      'left',
      'right'
    ],
    MemberExpression: [
      'object',
      'property'
    ],
    NewExpression: [
      'callee',
      'arguments'
    ],
    ObjectExpression: [
      'properties'
    ],
    Program: [
      'body'
    ],
    Property: [
      'key',
      'value'
    ],
    ReturnStatement: [
      'argument'
    ],
    SequenceExpression: [
      'expressions'
    ],
    SwitchStatement: [
      'descriminant',
      'cases'
    ],
    SwitchCase: [
      'test',
      'consequent'
    ],
    ThisExpression: [],
    ThrowStatement: [
      'argument'
    ],
    TryStatement: [
      'block',
      'handlers',
      'finalizer'
    ],
    UnaryExpression: [
      'argument'
    ],
    UpdateExpression: [
      'argument'
    ],
    VariableDeclaration: [
      'declarations'
    ],
    VariableDeclarator: [
      'id',
      'init'
    ],
    WhileStatement: [
      'test',
      'body'
    ],
    WithStatement: [
      'object',
      'body'
    ],
    PointerType: [
      'base'
    ],
    StructType: [
      'id',
      'fields'
    ],
    FieldDeclarator: [
      'id',
      'decltype'
    ],
    ArrowType: [
      'params',
      'return'
    ],
    TypeIdentifier: [],
    TypeAliasDirective: [
      'original',
      'alias'
    ],
    CastExpression: [
      'as',
      'argument'
    ]
  };
  VisitorOption = {
    Break: 1,
    Skip: 2
  };
  function traverse(top, visitor) {
    var worklist, leavelist, node, ret, current, current2, candidates, candidate;
    worklist = [
      top
    ];
    leavelist = [];
    while (worklist.length) {
      node = worklist.pop();
      if (node) {
        if (visitor.enter) {
          ret = visitor.enter(node);
        } else {
          ret = undefined;
        }
        if (ret === VisitorOption.Break) {
          return;
        }
        worklist.push(null);
        leavelist.push(node);
        if (ret !== VisitorOption.Skip) {
          candidates = VisitorKeys[node.type];
          current = candidates.length;
          while ((current -= 1) >= 0) {
            candidate = node[candidates[current]];
            if (candidate) {
              if (isArray(candidate)) {
                current2 = candidate.length;
                while ((current2 -= 1) >= 0) {
                  if (candidate[current2]) {
                    worklist.push(candidate[current2]);
                  }
                }
              } else {
                worklist.push(candidate);
              }
            }
          }
        }
      } else {
        node = leavelist.pop();
        if (visitor.leave) {
          ret = visitor.leave(node);
        } else {
          ret = undefined;
        }
        if (ret === VisitorOption.Break) {
          return;
        }
      }
    }
  }
  function upperBound(array, func) {
    var diff, len, i, current;
    len = array.length;
    i = 0;
    while (len) {
      diff = len >>> 1;
      current = i + diff;
      if (func(array[current])) {
        len = diff;
      } else {
        i = current + 1;
        len -= diff + 1;
      }
    }
    return i;
  }
  function lowerBound(array, func) {
    var diff, len, i, current;
    len = array.length;
    i = 0;
    while (len) {
      diff = len >>> 1;
      current = i + diff;
      if (func(array[current])) {
        i = current + 1;
        len -= diff + 1;
      } else {
        len = diff;
      }
    }
    return i;
  }
  function extendCommentRange(comment, tokens) {
    var target, token;
    target = upperBound(tokens, function search(token) {
      return token.range[0] > comment.range[0];
    });
    comment.extendedRange = [
      comment.range[0],
      comment.range[1]
    ];
    if (target !== tokens.length) {
      comment.extendedRange[1] = tokens[target].range[0];
    }
    target -= 1;
    if (target >= 0) {
      if (target < tokens.length) {
        comment.extendedRange[0] = tokens[target].range[1];
      } else if (token.length) {
        comment.extendedRange[1] = tokens[tokens.length - 1].range[0];
      }
    }
    return comment;
  }
  function attachComments(tree, providedComments, tokens) {
    var comments = [], comment, len, i;
    if (!tree.range) {
      throw new Error('attachComments needs range information');
    }
    if (!tokens.length) {
      if (providedComments.length) {
        for (i = 0, len = providedComments.length; i < len; i += 1) {
          comment = deepCopy(providedComments[i]);
          comment.extendedRange = [
            0,
            tree.range[0]
          ];
          comments.push(comment);
        }
        tree.leadingComments = comments;
      }
      return tree;
    }
    for (i = 0, len = providedComments.length; i < len; i += 1) {
      comments.push(extendCommentRange(deepCopy(providedComments[i]), tokens));
    }
    traverse(tree, {
      cursor: 0,
      enter: function (node) {
        var comment;
        while (this.cursor < comments.length) {
          comment = comments[this.cursor];
          if (comment.extendedRange[1] > node.range[0]) {
            break;
          }
          if (comment.extendedRange[1] === node.range[0]) {
            if (!node.leadingComments) {
              node.leadingComments = [];
            }
            node.leadingComments.push(comment);
            comments.splice(this.cursor, 1);
          } else {
            this.cursor += 1;
          }
        }
        if (this.cursor === comments.length) {
          return VisitorOption.Break;
        }
        if (comments[this.cursor].extendedRange[0] > node.range[1]) {
          return VisitorOption.Skip;
        }
      }
    });
    traverse(tree, {
      cursor: 0,
      leave: function (node) {
        var comment;
        while (this.cursor < comments.length) {
          comment = comments[this.cursor];
          if (node.range[1] < comment.extendedRange[0]) {
            break;
          }
          if (node.range[1] === comment.extendedRange[0]) {
            if (!node.trailingComments) {
              node.trailingComments = [];
            }
            node.trailingComments.push(comment);
            comments.splice(this.cursor, 1);
          } else {
            this.cursor += 1;
          }
        }
        if (this.cursor === comments.length) {
          return VisitorOption.Break;
        }
        if (comments[this.cursor].extendedRange[0] > node.range[1]) {
          return VisitorOption.Skip;
        }
      }
    });
    return tree;
  }
  exports.version = '0.0.6-dev';
  exports.generate = generate;
  exports.traverse = traverse;
  exports.attachComments = attachComments;
}(typeof exports === 'undefined' ? escodegen = {} : exports));
var verifierOptions = systemOptions.register(new OptionSet('Verifier Options'));
var verifierTraceLevel = verifierOptions.register(new Option('tv', 'tv', 'number', 0, 'Verifier Trace Level'));
var Type = function () {
    function type() {
      unexpected('Type is Abstract');
    }
    type.prototype.equals = function (other) {
      return this === other;
    };
    type.prototype.merge = function (other) {
      unexpected('Merging ' + this + ' with ' + other);
    };
    type.cache = {
      name: {},
      classInfo: [],
      instanceInfo: [],
      scriptInfo: [],
      methodInfo: []
    };
    type.from = function from(x, domain) {
      var traitsTypeCache = null;
      if (x instanceof ClassInfo) {
        traitsTypeCache = type.cache.classInfo;
      } else if (x instanceof InstanceInfo) {
        traitsTypeCache = type.cache.instanceInfo;
      } else if (x instanceof ScriptInfo) {
        traitsTypeCache = type.cache.scriptInfo;
      }
      if (traitsTypeCache) {
        return traitsTypeCache[x.runtimeId] || (traitsTypeCache[x.runtimeId] = new TraitsType(x, domain));
      }
      if (x instanceof ActivationInfo) {
        return new TraitsType(x.methodInfo);
      } else if (x instanceof Global) {
        return new TraitsType(x.scriptInfo);
      } else if (x instanceof Interface) {
        return new TraitsType(x.classInfo, domain);
      } else if (x instanceof MethodInfo) {
        return new MethodType(x);
      } else if (domain && x instanceof Class) {
        return type.from(x.classInfo, domain);
      }
      return Type.Any;
    };
    type.fromSimpleName = function (name, domain) {
      return Type.fromName(Multiname.fromSimpleName(name), domain);
    };
    type.fromName = function fromName(mn, domain) {
      if (mn === undefined) {
        return Type.Undefined;
      } else {
        var qn = Multiname.isQName(mn) ? Multiname.getFullQualifiedName(mn) : undefined;
        if (qn) {
          var ty = type.cache.name[qn];
          if (ty) {
            return ty;
          }
        }
        if (qn === Multiname.getPublicQualifiedName('void')) {
          return Type.Void;
        }
        true;
        ty = domain.findClassInfo(mn);
        ty = ty ? type.from(ty, domain) : Type.Any;
        if (mn.hasTypeParameter()) {
          ty = new ParameterizedType(ty, type.fromName(mn.typeParameter, domain));
        }
        return type.cache.name[qn] = ty;
      }
    };
    type.prototype.applyType = function (parameter) {
      return new ParameterizedType(this, parameter);
    };
    type.prototype.toString = function () {
      return '[type]';
    };
    type.prototype.isNumeric = function () {
      return this === Type.Int || this === Type.Uint || this === Type.Number;
    };
    type.prototype.isString = function () {
      return this === Type.String;
    };
    type.prototype.isDirectlyReadable = function () {
      return this === Type.Array;
    };
    type.prototype.isIndexedReadable = function () {
      return this.isParameterizedType();
    };
    type.prototype.isDirectlyWriteable = function () {
      return this === Type.Array;
    };
    type.prototype.isIndexedWriteable = function () {
      return this.isParameterizedType();
    };
    type.prototype.isVector = function () {
      return this.isParameterizedType();
    };
    type.prototype.isNotDirectlyIndexable = function () {
      return this === Type.Any || this === Type.XML || this === Type.XMLList || this === Type.Dictionary;
    };
    type.prototype.isParameterizedType = function () {
      return this instanceof ParameterizedType;
    };
    type.prototype.instanceType = function () {
      return this;
    };
    type.prototype.getTrait = function () {
      return null;
    };
    type.prototype.super = function () {
      unexpected('Can\'t call super on ' + this);
    };
    type.prototype.isSubtypeOf = function (other) {
      if (this === other || this.equals(other)) {
        return true;
      }
      return this.merge(other) === this;
    };
    var typesInitialized = false;
    type.initializeTypes = function (domain) {
      if (typesInitialized) {
        return;
      }
      type.Any = new AtomType('Any');
      type.Null = new AtomType('Null');
      type.Undefined = new AtomType('Undefined');
      type.Void = new AtomType('Void');
      type.Int = Type.fromSimpleName('int', domain).instanceType();
      type.Uint = Type.fromSimpleName('uint', domain).instanceType();
      type.Class = Type.fromSimpleName('Class', domain).instanceType();
      type.Array = Type.fromSimpleName('Array', domain).instanceType();
      type.Object = Type.fromSimpleName('Object', domain).instanceType();
      type.String = Type.fromSimpleName('String', domain).instanceType();
      type.Number = Type.fromSimpleName('Number', domain).instanceType();
      type.Boolean = Type.fromSimpleName('Boolean', domain).instanceType();
      type.Function = Type.fromSimpleName('Function', domain).instanceType();
      type.XML = Type.fromSimpleName('XML', domain).instanceType();
      type.XMLList = Type.fromSimpleName('XMLList', domain).instanceType();
      type.Dictionary = Type.fromSimpleName('flash.utils.Dictionary', domain).instanceType();
      typesInitialized = true;
    };
    return type;
  }();
var AtomType = function () {
    function atomType(name) {
      this.name = name;
    }
    atomType.prototype = Object.create(Type.prototype);
    atomType.prototype.toString = function () {
      if (this === Type.Any) {
        return '?';
      } else if (this === Type.Undefined) {
        return '_';
      } else if (this === Type.Null) {
        return 'X';
      } else if (this === Type.Void) {
        return 'V';
      }
      unexpected();
    };
    atomType.prototype.merge = function merge(other) {
      if (other instanceof TraitsType) {
        return Type.Any;
      }
      if (this === other) {
        return this;
      }
      if (this === Type.Any || other === Type.Any) {
        return Type.Any;
      }
      return Type.Any;
    };
    return atomType;
  }();
var MethodType = function () {
    function methodType(methodInfo) {
      this.methodInfo = methodInfo;
    }
    methodType.prototype = Object.create(Type.prototype);
    methodType.prototype.toString = function () {
      return 'MT ' + this.methodInfo;
    };
    return methodType;
  }();
var TraitsType = function () {
    function traitsType(object, domain) {
      true;
      this.object = object;
      this.traits = object.traits;
      this.domain = domain;
      if (this.object instanceof InstanceInfo) {
        true;
      }
    }
    traitsType.prototype = Object.create(Type.prototype);
    function nameOf(x) {
      if (x instanceof ScriptInfo) {
        return 'SI';
      } else if (x instanceof ClassInfo) {
        return 'CI:' + x.instanceInfo.name.name;
      } else if (x instanceof InstanceInfo) {
        return 'II:' + x.name.name;
      } else if (x instanceof MethodInfo) {
        return 'MI';
      } else if (x instanceof ActivationInfo) {
        return 'AC';
      }
      true;
    }
    function findTraitBySlotId(traits, slotId) {
      for (var i = traits.length - 1; i >= 0; i--) {
        if (traits[i].slotId === slotId) {
          return traits[i];
        }
      }
      unexpected('Cannot find trait with slotId: ' + slotId + ' in ' + traits);
    }
    function findTraitByName(traits, mn, isSetter) {
      var isGetter = !isSetter;
      var trait;
      if (!Multiname.isQName(mn)) {
        if (mn instanceof MultinameType) {
          return;
        }
        true;
        var dy;
        for (var i = 0, j = mn.namespaces.length; i < j; i++) {
          var qn = mn.getQName(i);
          if (mn.namespaces[i].isDynamic()) {
            dy = qn;
          } else {
            if (trait = findTraitByName(traits, qn, isSetter)) {
              return trait;
            }
          }
        }
        if (dy) {
          return findTraitByName(traits, dy, isSetter);
        }
      } else {
        var qn = Multiname.getQualifiedName(mn);
        for (var i = 0, j = traits.length; i < j; i++) {
          trait = traits[i];
          if (Multiname.getQualifiedName(trait.name) === qn) {
            if (isSetter && trait.isGetter() || isGetter && trait.isSetter()) {
              continue;
            }
            return trait;
          }
        }
      }
    }
    traitsType.prototype.getTrait = function (mn, isSetter, followSuperType) {
      if (mn instanceof MultinameType) {
        return null;
      }
      if (mn.isAttribute()) {
        return null;
      }
      if (followSuperType && (this.isInstanceInfo() || this.isClassInfo())) {
        var that = this;
        do {
          var trait = that.getTrait(mn, isSetter, false);
          if (!trait) {
            that = that.super();
          }
        } while (!trait && that);
        return trait;
      } else {
        return findTraitByName(this.traits, mn, isSetter);
      }
    };
    traitsType.prototype.getTraitAt = function (i) {
      if (this.object instanceof ScriptInfo || this.object instanceof MethodInfo) {
        return findTraitBySlotId(this.traits, i);
      }
    };
    traitsType.prototype.toString = function () {
      switch (this) {
      case Type.Int:
        return 'I';
      case Type.Uint:
        return 'U';
      case Type.Array:
        return 'A';
      case Type.Object:
        return 'O';
      case Type.String:
        return 'S';
      case Type.Number:
        return 'N';
      case Type.Boolean:
        return 'B';
      case Type.Function:
        return 'F';
      }
      return nameOf(this.object);
    };
    traitsType.prototype.instanceType = function () {
      true;
      return this.instanceCache || (this.instanceCache = Type.from(this.object.instanceInfo, this.domain));
    };
    traitsType.prototype.classType = function () {
      true;
      return this.instanceCache || (this.instanceCache = Type.from(this.object.classInfo, this.domain));
    };
    traitsType.prototype.super = function () {
      if (this.object instanceof ClassInfo) {
        return Type.Class;
      }
      true;
      if (this.object.superName) {
        var result = Type.fromName(this.object.superName, this.domain).instanceType();
        true;
        return result;
      }
      return null;
    };
    traitsType.prototype.isScriptInfo = function () {
      return this.object instanceof ScriptInfo;
    };
    traitsType.prototype.isClassInfo = function () {
      return this.object instanceof ClassInfo;
    };
    traitsType.prototype.isInstanceInfo = function () {
      return this.object instanceof InstanceInfo;
    };
    traitsType.prototype.isInstanceOrClassInfo = function () {
      return this.isInstanceInfo() || this.isClassInfo();
    };
    traitsType.prototype.equals = function (other) {
      return this.traits === other.traits;
    };
    traitsType.prototype.merge = function (other) {
      if (other instanceof TraitsType) {
        if (this.equals(other)) {
          return this;
        }
        if (this.isNumeric() && other.isNumeric()) {
          return Type.Number;
        }
        if (this.isInstanceInfo() && other.isInstanceInfo()) {
          var path = [];
          for (var curr = this; curr; curr = curr.super()) {
            path.push(curr);
          }
          for (var curr = other; curr; curr = curr.super()) {
            for (var i = 0; i < path.length; i++) {
              if (path[i].equals(curr)) {
                return curr;
              }
            }
          }
          return Type.Object;
        }
      }
      return Type.Any;
    };
    return traitsType;
  }();
var MultinameType = function () {
    function multinameType(namespaces, name, flags) {
      this.namespaces = namespaces;
      this.name = name;
      this.flags = flags;
    }
    multinameType.prototype = Object.create(Type.prototype);
    multinameType.prototype.toString = function () {
      return 'MN';
    };
    return multinameType;
  }();
var ParameterizedType = function () {
    function parameterizedType(type, parameter) {
      this.type = type;
      this.parameter = parameter;
    }
    parameterizedType.prototype = Object.create(Type.prototype);
    parameterizedType.prototype.toString = function () {
      return this.type + '<' + this.parameter + '>';
    };
    parameterizedType.prototype.instanceType = function () {
      true;
      return new ParameterizedType(this.type.instanceType(), this.parameter.instanceType());
    };
    parameterizedType.prototype.equals = function (other) {
      if (other instanceof ParameterizedType) {
        return this.type.equals(other.type) && this.parameter.equals(other.parameter);
      }
      return false;
    };
    parameterizedType.prototype.merge = function (other) {
      if (other instanceof TraitsType) {
        if (this.equals(other)) {
          return this;
        }
      }
      return Type.Any;
    };
    return parameterizedType;
  }();
var TypeInformation = function () {
    function typeInformation() {
    }
    typeInformation.prototype.toString = function () {
      return toKeyValueArray(this).map(function (x) {
        return x[0] + ': ' + x[1];
      }).join(' | ');
    };
    return typeInformation;
  }();
var Verifier = function () {
    function VerifierError(message) {
      this.name = 'VerifierError';
      this.message = message || '';
    }
    var State = function () {
        var id = 0;
        function state() {
          this.id = id += 1;
          this.stack = [];
          this.scope = [];
          this.local = [];
        }
        state.prototype.clone = function clone() {
          var s = new State();
          s.originalId = this.id;
          s.stack = this.stack.slice(0);
          s.scope = this.scope.slice(0);
          s.local = this.local.slice(0);
          return s;
        };
        state.prototype.trace = function trace(writer) {
          writer.writeLn(this.toString());
        };
        state.prototype.toString = function () {
          return '<' + this.id + (this.originalId ? ':' + this.originalId : '') + ', L[' + this.local.join(', ') + ']' + ', S[' + this.stack.join(', ') + ']' + ', $[' + this.scope.join(', ') + ']>';
        };
        state.prototype.equals = function (other) {
          return arrayEquals(this.stack, other.stack) && arrayEquals(this.scope, other.scope) && arrayEquals(this.local, other.local);
        };
        function arrayEquals(a, b) {
          if (a.length != b.length) {
            return false;
          }
          for (var i = a.length - 1; i >= 0; i--) {
            if (!a[i].equals(b[i])) {
              return false;
            }
          }
          return true;
        }
        state.prototype.isSubset = function (other) {
          return arraySubset(this.stack, other.stack) && arraySubset(this.scope, other.scope) && arraySubset(this.local, other.local);
        };
        function arraySubset(a, b) {
          if (a.length != b.length) {
            return false;
          }
          for (var i = a.length - 1; i >= 0; i--) {
            if (a[i] === b[i] || a[i].equals(b[i])) {
              continue;
            }
            if (a[i].merge(b[i]) !== a[i]) {
              return false;
            }
          }
          return true;
        }
        state.prototype.merge = function (other) {
          mergeArrays(this.local, other.local);
          mergeArrays(this.stack, other.stack);
          mergeArrays(this.scope, other.scope);
        };
        function mergeArrays(a, b) {
          true;
          for (var i = a.length - 1; i >= 0; i--) {
            true;
            if (a[i] === b[i]) {
              continue;
            }
            a[i] = a[i].merge(b[i]);
          }
        }
        return state;
      }();
    var Verification = function () {
        function verification(methodInfo, domain, savedScope) {
          this.savedScope = savedScope;
          this.methodInfo = methodInfo;
          this.domain = domain;
          this.writer = new IndentingWriter();
          this.returnType = Type.Undefined;
        }
        verification.prototype.verify = function verify() {
          var mi = this.methodInfo;
          var writer = verifierTraceLevel.value ? this.writer : null;
          var blocks = mi.analysis.blocks;
          blocks.forEach(function (x) {
            x.entryState = x.exitState = null;
          });
          if (writer) {
            this.methodInfo.trace(writer);
          }
          var entryState = new State();
          true;
          this.thisType = mi.holder ? Type.from(mi.holder, this.domain) : Type.Any;
          entryState.local.push(this.thisType);
          for (var i = 0; i < mi.parameters.length; i++) {
            entryState.local.push(Type.fromName(mi.parameters[i].type, this.domain).instanceType());
          }
          var remainingLocals = mi.localCount - mi.parameters.length - 1;
          if (mi.needsRest() || mi.needsArguments()) {
            entryState.local.push(Type.Array);
            remainingLocals -= 1;
          }
          for (var i = 0; i < remainingLocals; i++) {
            entryState.local.push(Type.Undefined);
          }
          true;
          if (writer) {
            entryState.trace(writer);
          }
          for (var bi = 0, len = blocks.length; bi < len; bi++) {
            blocks[bi].bdo = bi;
          }
          var worklist = new Shumway.SortedList(function compare(blockA, blockB) {
              return blockA.bdo - blockB.bdo;
            });
          blocks[0].entryState = entryState;
          worklist.push(blocks[0]);
          while (!worklist.isEmpty()) {
            var block = worklist.pop();
            var exitState = block.exitState = block.entryState.clone();
            this.verifyBlock(block, exitState);
            block.succs.forEach(function (successor) {
              if (worklist.contains(successor)) {
                if (writer) {
                  writer.writeLn('Forward Merged Block: ' + successor.bid + ' ' + exitState.toString() + ' with ' + successor.entryState.toString());
                }
                successor.entryState.merge(exitState);
                if (writer) {
                  writer.writeLn('Merged State: ' + successor.entryState);
                }
                return;
              }
              if (successor.entryState) {
                if (!successor.entryState.isSubset(exitState)) {
                  if (writer) {
                    writer.writeLn('Backward Merged Block: ' + block.bid + ' with ' + successor.bid + ' ' + exitState.toString() + ' with ' + successor.entryState.toString());
                  }
                  successor.entryState.merge(exitState);
                  worklist.push(successor);
                  if (writer) {
                    writer.writeLn('Merged State: ' + successor.entryState);
                  }
                }
                return;
              }
              successor.entryState = exitState.clone();
              worklist.push(successor);
              if (writer) {
                writer.writeLn('Added Block: ' + successor.bid + ' to worklist: ' + successor.entryState.toString());
              }
            });
          }
          if (writer) {
            writer.writeLn('Inferred return type: ' + this.returnType);
          }
          this.methodInfo.inferredReturnType = this.returnType;
        };
        verification.prototype.verifyBlock = function verifyBlock(block, state) {
          var savedScope = this.savedScope;
          var globalScope = savedScope[0];
          var local = state.local;
          var stack = state.stack;
          var scope = state.scope;
          var writer = verifierTraceLevel.value ? this.writer : null;
          var bytecodes = this.methodInfo.analysis.bytecodes;
          var domain = this.domain;
          var multinames = this.methodInfo.abc.constantPool.multinames;
          var mi = this.methodInfo;
          var bc, obj, fn, mn, l, r, val, type, returnType;
          if (writer) {
            writer.enter('verifyBlock: ' + block.bid + ', range: [' + block.position + ', ' + block.end.position + '], entryState: ' + state.toString() + ' {');
          }
          function construct(obj) {
            if (obj instanceof TraitsType || obj instanceof ParameterizedType) {
              if (obj === Type.Function || obj === Type.Class || obj === Type.Object) {
                return Type.Object;
              }
              return obj.instanceType();
            } else {
              return Type.Any;
            }
          }
          function ti() {
            return bc.ti || (bc.ti = new TypeInformation());
          }
          function push(x) {
            true;
            ti().type = x;
            stack.push(x);
          }
          function pop() {
            return stack.pop();
          }
          function findProperty(mn, strict) {
            if (mn instanceof MultinameType) {
              if (mn.name === 'Array') {
                debugger;
              }
              return Type.Any;
            }
            for (var i = scope.length - 1; i >= -savedScope.length; i--) {
              var s = i >= 0 ? scope[i] : savedScope[savedScope.length + i];
              if (s instanceof TraitsType) {
                var trait = s.getTrait(mn, false, true);
                if (trait) {
                  ti().scopeDepth = scope.length - i - 1;
                  if (s.isClassInfo() || s.isScriptInfo()) {
                    ti().object = LazyInitializer.create(s.object);
                  }
                  return s;
                }
              } else {
                if (mn.name === 'Array') {
                  debugger;
                }
                return Type.Any;
              }
            }
            var resolved = domain.findDefiningScript(mn, false);
            if (resolved) {
              ti().object = LazyInitializer.create(resolved.script);
              return Type.from(resolved.script, domain);
            }
            if (mn.name === 'Array') {
              debugger;
            }
            return Type.Any;
          }
          function popMultiname() {
            var mn = multinames[bc.index];
            if (mn.isRuntime()) {
              var namespaces = mn.namespaces;
              var name = mn.name;
              if (mn.isRuntimeName()) {
                name = pop();
              }
              if (mn.isRuntimeNamespace()) {
                namespaces = [
                  pop()
                ];
              }
              return new MultinameType(namespaces, name, mn.flags);
            }
            return mn;
          }
          function accessSlot(obj) {
            if (obj instanceof TraitsType) {
              var trait = obj.getTraitAt(bc.index);
              writer && writer.debugLn('accessSlot() -> ' + trait);
              if (trait) {
                ti().trait = trait;
                if (trait.isSlot()) {
                  return Type.fromName(trait.typeName, domain).instanceType();
                } else if (trait.isClass()) {
                  return Type.from(trait.classInfo, domain);
                }
              }
            }
            return Type.Any;
          }
          function isNumericMultiname(mn) {
            return mn instanceof Multiname && Multiname.isNumeric(mn) || mn instanceof MultinameType && (mn.name instanceof TraitsType && mn.name.isNumeric());
          }
          function getProperty(obj, mn) {
            if (obj instanceof TraitsType || obj instanceof ParameterizedType) {
              var trait = obj.getTrait(mn, false, true);
              writer && writer.debugLn('getProperty(' + mn + ') -> ' + trait);
              if (trait) {
                ti().trait = trait;
                if (trait.isSlot() || trait.isConst()) {
                  return Type.fromName(trait.typeName, domain).instanceType();
                } else if (trait.isGetter()) {
                  return Type.fromName(trait.methodInfo.returnType, domain).instanceType();
                } else if (trait.isClass()) {
                  return Type.from(trait.classInfo, domain);
                } else if (trait.isMethod()) {
                  return Type.from(trait.methodInfo, domain);
                }
              } else if (obj.isDirectlyReadable() && mn instanceof Multiname) {
                ti().propertyQName = Multiname.getPublicQualifiedName(mn.name);
              }
              if (isNumericMultiname(mn)) {
                if (obj.isIndexedReadable()) {
                  ti().isIndexedReadable = true;
                  if (obj.isVector()) {
                    return obj.parameter;
                  }
                } else if (obj.isDirectlyReadable()) {
                  ti().isDirectlyReadable = true;
                }
              }
            }
            return Type.Any;
          }
          function setProperty(obj, mn, value) {
            if (obj instanceof TraitsType || obj instanceof ParameterizedType) {
              var trait = obj.getTrait(mn, true, true);
              writer && writer.debugLn('setProperty(' + mn + ') -> ' + trait);
              if (trait) {
                ti().trait = trait;
              } else if (obj.isDirectlyWriteable() && mn instanceof Multiname) {
                ti().propertyQName = Multiname.getPublicQualifiedName(mn.name);
              }
              if (isNumericMultiname(mn)) {
                if (obj.isDirectlyWriteable()) {
                  ti().isDirectlyWriteable = true;
                } else if (obj.isVector()) {
                  ti().isIndexedWriteable = true;
                }
              }
            }
          }
          for (var bci = block.position, end = block.end.position; bci <= end; bci++) {
            bc = bytecodes[bci];
            var op = bc.op;
            if (writer && verifierTraceLevel.value > 1) {
              writer.writeLn(('stateBefore: ' + state.toString() + ' $$[' + savedScope.join(', ') + ']').padRight(' ', 100) + ' : ' + bci + ', ' + bc.toString(mi.abc));
            }
            switch (op) {
            case 1:
              break;
            case 3:
              pop();
              break;
            case 4:
              mn = popMultiname();
              obj = pop();
              true;
              ti().baseClass = LazyInitializer.create(this.thisType.super().classType().object);
              push(getProperty(obj.super(), mn));
              break;
            case 5:
              val = pop();
              mn = popMultiname();
              obj = pop();
              true;
              ti().baseClass = LazyInitializer.create(this.thisType.super().classType().object);
              setProperty(obj.super(), mn, val);
              break;
            case 6:
              notImplemented(bc);
              break;
            case 7:
              notImplemented(bc);
              break;
            case 8:
              state.local[bc.index] = Type.Undefined;
              break;
            case 10:
              notImplemented(bc);
              break;
            case 11:
              notImplemented(bc);
              break;
            case 12:
            case 24:
            case 13:
            case 23:
            case 14:
            case 22:
            case 15:
            case 21:
            case 19:
            case 20:
            case 25:
            case 26:
              pop();
              pop();
              break;
            case 16:
              break;
            case 17:
            case 18:
              pop();
              break;
            case 27:
              pop(Type.Int);
              break;
            case 29:
              scope.pop();
              break;
            case 30:
            case 35:
              pop(Type.Int);
              pop();
              push(Type.Any);
              break;
            case 31:
              push(Type.Boolean);
              break;
            case 50:
              push(Type.Boolean);
              break;
            case 32:
              push(Type.Null);
              break;
            case 33:
              push(Type.Undefined);
              break;
            case 34:
              notImplemented(bc);
              break;
            case 36:
              push(Type.Int);
              break;
            case 37:
              push(Type.Int);
              break;
            case 44:
              push(Type.String);
              break;
            case 45:
              push(Type.Int);
              break;
            case 46:
              push(Type.Uint);
              break;
            case 47:
              push(Type.Number);
              break;
            case 38:
              push(Type.Boolean);
              break;
            case 39:
              push(Type.Boolean);
              break;
            case 40:
              push(Type.Number);
              break;
            case 41:
              pop();
              break;
            case 42:
              val = pop();
              push(val);
              push(val);
              break;
            case 43:
              l = pop();
              r = pop();
              push(l);
              push(r);
              break;
            case 28:
              pop();
              scope.push(Type.Any);
              break;
            case 48:
              scope.push(pop());
              break;
            case 49:
              notImplemented(bc);
              break;
            case 53:
            case 54:
            case 55:
              push(Type.Int);
              break;
            case 56:
            case 57:
              push(Type.Number);
              break;
            case 58:
            case 59:
            case 60:
              pop(Type.Int);
              break;
            case 61:
            case 62:
              pop(Type.Number);
              break;
            case 64:
              push(Type.Function);
              break;
            case 65:
              stack.popMany(bc.argCount);
              obj = pop();
              fn = pop();
              push(Type.Any);
              break;
            case 67:
              throw new VerifierError('callmethod');
            case 68:
              notImplemented(bc);
              break;
            case 69:
            case 78:
            case 79:
            case 70:
            case 76:
              stack.popMany(bc.argCount);
              mn = popMultiname();
              obj = pop();
              if (op === OP_callsuper || op === OP_callsupervoid) {
                obj = this.thisType.super();
                ti().baseClass = LazyInitializer.create(this.thisType.super().classType().object);
              }
              type = getProperty(obj, mn);
              if (op === OP_callpropvoid || op === OP_callsupervoid) {
                break;
              }
              if (type instanceof MethodType) {
                returnType = Type.fromName(type.methodInfo.returnType, domain).instanceType();
              } else if (type instanceof TraitsType && type.isClassInfo()) {
                returnType = type.instanceType();
              } else {
                returnType = Type.Any;
              }
              push(returnType);
              break;
            case 71:
              this.returnType.merge(Type.Undefined);
              break;
            case 72:
              type = pop();
              if (mi.returnType) {
                var coerceType = Type.fromName(mi.returnType, this.domain).instanceType();
                if (coerceType.isSubtypeOf(type)) {
                  ti().noCoercionNeeded = true;
                }
              }
              break;
            case 73:
              stack.popMany(bc.argCount);
              stack.pop();
              if (this.thisType.isInstanceInfo() && this.thisType.super() === Type.Object) {
                ti().noCallSuperNeeded = true;
              } else {
                ti().baseClass = LazyInitializer.create(this.thisType.super().classType().object);
              }
              break;
            case 66:
              stack.popMany(bc.argCount);
              push(construct(pop()));
              break;
            case 74:
              stack.popMany(bc.argCount);
              mn = popMultiname();
              push(construct(getProperty(stack.pop(), mn)));
              break;
            case 75:
              notImplemented(bc);
              break;
            case 77:
              notImplemented(bc);
              break;
            case 80:
            case 81:
            case 82:
              break;
            case 83:
              true;
              val = pop();
              obj = pop();
              if (obj === Type.Any) {
                push(Type.Any);
              } else {
                push(obj.applyType(val));
              }
              break;
            case 84:
              notImplemented(bc);
              break;
            case 85:
              stack.popMany(bc.argCount * 2);
              push(Type.Object);
              break;
            case 86:
              stack.popMany(bc.argCount);
              push(Type.Array);
              break;
            case 87:
              push(Type.from(new ActivationInfo(this.methodInfo)));
              break;
            case 88:
              push(Type.Any);
              break;
            case 89:
              popMultiname();
              pop();
              push(Type.XMLList);
              break;
            case 90:
              push(Type.Any);
              break;
            case 93:
              push(findProperty(popMultiname(), true));
              break;
            case 94:
              push(findProperty(popMultiname(), false));
              break;
            case 95:
              notImplemented(bc);
              break;
            case 96:
              mn = popMultiname();
              push(getProperty(findProperty(mn, true), mn));
              break;
            case 104:
            case 97:
              val = pop();
              mn = popMultiname();
              obj = pop();
              setProperty(obj, mn, val, bc);
              break;
            case 98:
              push(local[bc.index]);
              break;
            case 99:
              local[bc.index] = pop();
              break;
            case 100:
              push(globalScope);
              ti().object = LazyInitializer.create(globalScope.object);
              break;
            case 101:
              push(scope[bc.index]);
              break;
            case 102:
              mn = popMultiname();
              obj = pop();
              push(getProperty(obj, mn));
              break;
            case 103:
              notImplemented(bc);
              break;
            case 105:
              notImplemented(bc);
              break;
            case 106:
              popMultiname();
              pop();
              push(Type.Boolean);
              break;
            case 107:
              notImplemented(bc);
              break;
            case 108:
              push(accessSlot(pop()));
              break;
            case 109:
              val = pop();
              obj = pop();
              accessSlot(obj);
              break;
            case 110:
              notImplemented(bc);
              break;
            case 111:
              notImplemented(bc);
              break;
            case 112:
              pop();
              push(Type.String);
              break;
            case 113:
              pop();
              push(Type.String);
              break;
            case 114:
              pop();
              push(Type.String);
              break;
            case 131:
            case 115:
              pop();
              push(Type.Int);
              break;
            case 136:
            case 116:
              pop();
              push(Type.Uint);
              break;
            case 132:
            case 117:
              pop();
              push(Type.Number);
              break;
            case 129:
            case 118:
              pop();
              push(Type.Boolean);
              break;
            case 119:
              notImplemented(bc);
              break;
            case 120:
              break;
            case 121:
              pop();
              push(Type.Number);
              break;
            case 122:
              notImplemented(bc);
              break;
            case 123:
              notImplemented(bc);
              break;
            case 128:
              type = pop();
              var coerceType = Type.fromName(multinames[bc.index], this.domain).instanceType();
              if (coerceType.isSubtypeOf(type)) {
                ti().noCoercionNeeded = true;
              }
              push(coerceType);
              break;
            case 130:
              break;
            case 133:
              pop();
              push(Type.String);
              break;
            case 134:
              notImplemented(bc);
              break;
            case 135:
              type = pop();
              pop();
              if (type instanceof TraitsType) {
                push(type.instanceType());
              } else {
                push(Type.Any);
              }
              break;
            case 137:
              notImplemented(bc);
              break;
            case 144:
            case 145:
            case 147:
              pop();
              push(Type.Number);
              break;
            case 146:
            case 148:
              local[bc.index] = Type.Number;
              break;
            case 149:
              pop();
              push(Type.String);
              break;
            case 150:
              pop();
              push(Type.Boolean);
              break;
            case 160:
              r = pop();
              l = pop();
              if (l.isNumeric() && r.isNumeric()) {
                push(Type.Number);
              } else if (l === Type.String || r === Type.String) {
                push(Type.String);
              } else {
                push(Type.Any);
              }
              break;
            case 161:
            case 162:
            case 163:
            case 164:
              pop();
              pop();
              push(Type.Number);
              break;
            case 168:
            case 169:
            case 170:
            case 165:
            case 166:
            case 167:
              pop();
              pop();
              push(Type.Int);
              break;
            case 151:
              pop();
              push(Type.Int);
              break;
            case 171:
            case 172:
            case 173:
            case 174:
            case 175:
            case 176:
            case 177:
            case 180:
              pop();
              pop();
              push(Type.Boolean);
              break;
            case 178:
              pop();
              push(Type.Boolean);
              break;
            case 179:
              pop();
              pop();
              push(Type.Boolean);
              break;
            case 194:
            case 195:
              local[bc.index] = Type.Int;
              break;
            case 193:
            case 192:
            case 196:
              pop();
              push(Type.Int);
              break;
            case 197:
            case 198:
            case 199:
              pop();
              pop();
              push(Type.Int);
              break;
            case 208:
            case 209:
            case 210:
            case 211:
              push(local[op - OP_getlocal0]);
              break;
            case 212:
            case 213:
            case 214:
            case 215:
              local[op - OP_setlocal0] = pop();
              break;
            case 239:
              break;
            case 240:
              break;
            case 241:
              break;
            case 242:
              break;
            case 243:
              break;
            default:
              console.info('Not Implemented: ' + bc);
            }
            if (writer) {
              if (bc.ti) {
                writer.debugLn('> TI: ' + bc.ti);
              }
            }
          }
          if (writer) {
            writer.leave('}');
            writer.writeLn('verifiedBlock: ' + block.bid + ', range: [' + block.position + ', ' + block.end.position + '], exitState: ' + state.toString());
          }
        };
        return verification;
      }();
    function verifier() {
      this.writer = new IndentingWriter();
    }
    verifier.prototype.verifyMethod = function (methodInfo, scope) {
      try {
        var domain = methodInfo.abc.applicationDomain;
        var scopeObjects = scope.getScopeObjects();
        if (!scopeObjects[scopeObjects.length - 1]) {
          if (methodInfo.holder instanceof InstanceInfo) {
            scopeObjects[scopeObjects.length - 1] = methodInfo.holder.classInfo;
          } else if (methodInfo.holder instanceof ClassInfo) {
            scopeObjects[scopeObjects.length - 1] = methodInfo.holder;
          }
        }
        var savedScope = scopeObjects.map(function (object) {
            if (object instanceof MethodInfo) {
              return Type.from(new ActivationInfo(object));
            }
            return Type.from(object, domain);
          });
        new Verification(methodInfo, methodInfo.abc.applicationDomain, savedScope).verify();
        methodInfo.verified = true;
        Counter.count('Verifier: Methods');
      } catch (e) {
        if (e instanceof VerifierError) {
          return;
        }
        throw e;
      }
    };
    return verifier;
  }();
(function (exports) {
  var debug = false;
  var IRDefinition = {
      Control: {
        Region: {
          predecessors: {
            array: true,
            expand: 'control'
          },
          Start: {
            _constructorText: 'this.control = this;',
            scope: {
              dynamic: true
            },
            domain: {
              dynamic: true
            }
          }
        },
        End: {
          control: {
            assert: 'isControlOrNull'
          },
          Stop: {
            store: {
              assert: 'isStore'
            },
            argument: {
              assert: ''
            }
          },
          If: {
            predicate: {
              assert: ''
            }
          },
          Switch: {
            determinant: {
              assert: ''
            }
          },
          Jump: {}
        }
      },
      Value: {
        StoreDependent: {
          control: {
            assert: 'isControlOrNull',
            nullable: true
          },
          store: {
            assert: 'isStoreOrNull',
            nullable: true
          },
          loads: {
            dynamic: true,
            nullable: true,
            array: true
          },
          Call: {
            callee: {
              assert: ''
            },
            object: {
              assert: 'isValueOrNull',
              nullable: true
            },
            args: {
              assert: 'isArray',
              array: true
            },
            flags: {
              internal: true,
              assert: 'isNumber'
            }
          },
          CallProperty: {
            object: {
              assert: ''
            },
            name: {
              assert: ''
            },
            args: {
              assert: 'isArray',
              array: true
            },
            flags: {
              internal: true,
              assert: 'isNumber'
            },
            ASCallProperty: {
              isLex: {
                assert: '',
                internal: true
              }
            },
            ASCallSuper: {
              scope: {
                assert: ''
              }
            }
          },
          New: {
            callee: {
              assert: ''
            },
            args: {
              assert: '',
              array: true
            },
            ASNew: {}
          },
          GetProperty: {
            object: {
              assert: ''
            },
            name: {
              assert: ''
            },
            ASGetProperty: {
              flags: {
                internal: true,
                assert: 'isNumber'
              }
            },
            ASGetDescendants: {},
            ASHasProperty: {},
            ASGetSlot: {},
            ASGetSuper: {
              scope: {
                assert: ''
              }
            }
          },
          SetProperty: {
            object: {
              assert: ''
            },
            name: {
              assert: ''
            },
            value: {
              assert: ''
            },
            ASSetProperty: {
              flags: {
                internal: true
              }
            },
            ASSetSlot: {},
            ASSetSuper: {
              scope: {
                assert: ''
              }
            }
          },
          DeleteProperty: {
            object: {
              assert: ''
            },
            name: {
              assert: ''
            },
            ASDeleteProperty: {}
          },
          ASFindProperty: {
            scope: {
              assert: ''
            },
            name: {
              assert: ''
            },
            domain: {
              assert: ''
            },
            strict: {
              internal: true
            }
          }
        },
        Store: {},
        Phi: {
          control: {
            assert: 'isControl',
            nullable: true
          },
          args: {
            array: true,
            expand: 'value'
          }
        },
        Variable: {
          name: {
            internal: true
          }
        },
        Copy: {
          argument: {}
        },
        Move: {
          to: {},
          from: {}
        },
        Projection: {
          argument: {},
          type: {
            internal: true
          },
          selector: {
            internal: true,
            optional: true
          }
        },
        Latch: {
          control: {
            assert: 'isControlOrNull',
            nullable: true
          },
          condition: {},
          left: {},
          right: {}
        },
        Binary: {
          operator: {
            internal: true
          },
          left: {},
          right: {}
        },
        Unary: {
          operator: {
            internal: true
          },
          argument: {}
        },
        Constant: {
          value: {
            internal: true
          }
        },
        GlobalProperty: {
          name: {
            internal: true
          }
        },
        This: {
          control: {
            assert: 'isControl'
          }
        },
        Throw: {
          control: {
            assert: 'isControl'
          },
          argument: {}
        },
        Arguments: {
          control: {
            assert: 'isControl'
          }
        },
        Parameter: {
          control: {
            assert: 'isControl'
          },
          index: {
            internal: true
          },
          name: {
            internal: true
          }
        },
        NewArray: {
          control: {
            assert: 'isControl'
          },
          elements: {
            array: true
          }
        },
        NewObject: {
          control: {
            assert: 'isControl'
          },
          properties: {
            array: true
          }
        },
        KeyValuePair: {
          key: {},
          value: {}
        },
        ASScope: {
          parent: {},
          object: {},
          isWith: {
            internal: true
          }
        },
        ASGlobal: {
          control: {
            assert: 'isControlOrNull',
            nullable: true
          },
          scope: {
            assert: 'isScope'
          }
        },
        ASNewActivation: {
          methodInfo: {
            internal: true
          }
        },
        ASMultiname: {
          namespaces: {},
          name: {},
          flags: {
            internal: true
          }
        }
      }
    };
  function IRGenerator(root) {
    var str = '';
    function out(s) {
      str += s + '\n';
    }
    var writer = new IndentingWriter(false, out);
    function makeProperties(node) {
      var result = [];
      for (var k in node) {
        if (isProperty(k)) {
          node[k].name = k;
          result.push(node[k]);
        }
      }
      return result;
    }
    function isProperty(v) {
      if (v[0] === '_') {
        return false;
      }
      return v[0].toLowerCase() === v[0];
    }
    function generate(node, path) {
      path = path.concat([
        node
      ]);
      writer.enter('var ' + node._name + ' = (function () {');
      var constructorName = node._name[0].toLowerCase() + node._name.slice(1) + 'Node';
      if (constructorName.substring(0, 2) === 'aS') {
        constructorName = 'as' + constructorName.substring(2);
      }
      var prototypeName = constructorName + '.prototype';
      var properties = path.reduce(function (a, v) {
          return a.concat(makeProperties(v));
        }, []);
      var parameters = properties.filter(function (property) {
          return !property.dynamic;
        });
      var optionalParameters = parameters.filter(function (property) {
          return property.optional;
        });
      var parameterString = parameters.map(function (property) {
          if (property.expand) {
            return property.expand;
          }
          return property.name;
        }).join(', ');
      writer.enter('function ' + constructorName + '(' + parameterString + ') {');
      if (true) {
        properties.forEach(function (property) {
          if (property.assert === '') {
            writer.writeLn('release || assert (!(' + property.name + ' == undefined), "' + property.name + '");');
          } else if (property.assert) {
            writer.writeLn('release || assert (' + property.assert + '(' + property.name + '), "' + property.name + '");');
          }
        });
        writer.writeLn('release || assert (arguments.length >= ' + (parameters.length - optionalParameters.length) + ', "' + node._name + ' not enough args.");');
      }
      if (node._constructorText) {
        writer.writeLn(node._constructorText);
      }
      properties.forEach(function (property) {
        if (property.expand) {
          writer.writeLn('this.' + property.name + ' = ' + property.expand + ' ? [' + property.expand + '] : [];');
        } else if (property.dynamic) {
          writer.writeLn('this.' + property.name + ' = undefined;');
        } else {
          writer.writeLn('this.' + property.name + ' = ' + property.name + ';');
        }
      });
      writer.writeLn('this.id = nextID[nextID.length - 1] += 1;');
      writer.leave('}');
      if (path.length > 1) {
        writer.writeLn(prototypeName + ' = ' + 'extend(' + path[path.length - 2]._name + ', "' + node._name + '");');
      }
      writer.writeLn(prototypeName + '.nodeName = "' + node._name + '";');
      writer.enter(prototypeName + '.visitInputs = function (visitor) {');
      properties.forEach(function (property) {
        if (property.internal) {
          return;
        }
        var str = '';
        if (property.nullable) {
          str += 'this.' + property.name + ' && ';
        }
        if (property.array) {
          str += 'visitArrayInputs(this.' + property.name + ', visitor);';
        } else {
          str += 'visitor(this.' + property.name + ');';
        }
        writer.writeLn(str);
      });
      writer.leave('};');
      writer.writeLn('return ' + constructorName + ';');
      writer.leave('})();');
      writer.writeLn('');
      for (var name in node) {
        if (name[0] === '_' || isProperty(name)) {
          continue;
        }
        var child = node[name];
        child._name = name;
        generate(child, path);
      }
    }
    IRDefinition._name = 'Node';
    generate(IRDefinition, []);
    return str;
  }
  var nextID = [];
  var Node = function () {
      function nodeNode() {
        true;
        this.id = nextID[nextID.length - 1] += 1;
      }
      nodeNode.prototype.nodeName = 'Node';
      nodeNode.prototype.visitInputs = function (visitor) {
      };
      return nodeNode;
    }();
  var Control = function () {
      function controlNode() {
        true;
        this.id = nextID[nextID.length - 1] += 1;
      }
      controlNode.prototype = extend(Node, 'Control');
      controlNode.prototype.nodeName = 'Control';
      controlNode.prototype.visitInputs = function (visitor) {
      };
      return controlNode;
    }();
  var Region = function () {
      function regionNode(control) {
        true;
        this.predecessors = control ? [
          control
        ] : [];
        this.id = nextID[nextID.length - 1] += 1;
      }
      regionNode.prototype = extend(Control, 'Region');
      regionNode.prototype.nodeName = 'Region';
      regionNode.prototype.visitInputs = function (visitor) {
        visitArrayInputs(this.predecessors, visitor);
      };
      return regionNode;
    }();
  var Start = function () {
      function startNode(control) {
        true;
        this.control = this;
        this.predecessors = control ? [
          control
        ] : [];
        this.scope = undefined;
        this.domain = undefined;
        this.id = nextID[nextID.length - 1] += 1;
      }
      startNode.prototype = extend(Region, 'Start');
      startNode.prototype.nodeName = 'Start';
      startNode.prototype.visitInputs = function (visitor) {
        visitArrayInputs(this.predecessors, visitor);
        visitor(this.scope);
        visitor(this.domain);
      };
      return startNode;
    }();
  var End = function () {
      function endNode(control) {
        true;
        true;
        this.control = control;
        this.id = nextID[nextID.length - 1] += 1;
      }
      endNode.prototype = extend(Control, 'End');
      endNode.prototype.nodeName = 'End';
      endNode.prototype.visitInputs = function (visitor) {
        visitor(this.control);
      };
      return endNode;
    }();
  var Stop = function () {
      function stopNode(control, store, argument) {
        true;
        true;
        true;
        true;
        this.control = control;
        this.store = store;
        this.argument = argument;
        this.id = nextID[nextID.length - 1] += 1;
      }
      stopNode.prototype = extend(End, 'Stop');
      stopNode.prototype.nodeName = 'Stop';
      stopNode.prototype.visitInputs = function (visitor) {
        visitor(this.control);
        visitor(this.store);
        visitor(this.argument);
      };
      return stopNode;
    }();
  var If = function () {
      function ifNode(control, predicate) {
        true;
        true;
        true;
        this.control = control;
        this.predicate = predicate;
        this.id = nextID[nextID.length - 1] += 1;
      }
      ifNode.prototype = extend(End, 'If');
      ifNode.prototype.nodeName = 'If';
      ifNode.prototype.visitInputs = function (visitor) {
        visitor(this.control);
        visitor(this.predicate);
      };
      return ifNode;
    }();
  var Switch = function () {
      function switchNode(control, determinant) {
        true;
        true;
        true;
        this.control = control;
        this.determinant = determinant;
        this.id = nextID[nextID.length - 1] += 1;
      }
      switchNode.prototype = extend(End, 'Switch');
      switchNode.prototype.nodeName = 'Switch';
      switchNode.prototype.visitInputs = function (visitor) {
        visitor(this.control);
        visitor(this.determinant);
      };
      return switchNode;
    }();
  var Jump = function () {
      function jumpNode(control) {
        true;
        true;
        this.control = control;
        this.id = nextID[nextID.length - 1] += 1;
      }
      jumpNode.prototype = extend(End, 'Jump');
      jumpNode.prototype.nodeName = 'Jump';
      jumpNode.prototype.visitInputs = function (visitor) {
        visitor(this.control);
      };
      return jumpNode;
    }();
  var Value = function () {
      function valueNode() {
        true;
        this.id = nextID[nextID.length - 1] += 1;
      }
      valueNode.prototype = extend(Node, 'Value');
      valueNode.prototype.nodeName = 'Value';
      valueNode.prototype.visitInputs = function (visitor) {
      };
      return valueNode;
    }();
  var StoreDependent = function () {
      function storeDependentNode(control, store) {
        true;
        true;
        true;
        this.control = control;
        this.store = store;
        this.loads = undefined;
        this.id = nextID[nextID.length - 1] += 1;
      }
      storeDependentNode.prototype = extend(Value, 'StoreDependent');
      storeDependentNode.prototype.nodeName = 'StoreDependent';
      storeDependentNode.prototype.visitInputs = function (visitor) {
        this.control && visitor(this.control);
        this.store && visitor(this.store);
        this.loads && visitArrayInputs(this.loads, visitor);
      };
      return storeDependentNode;
    }();
  var Call = function () {
      function callNode(control, store, callee, object, args, flags) {
        true;
        true;
        true;
        true;
        true;
        true;
        true;
        this.control = control;
        this.store = store;
        this.loads = undefined;
        this.callee = callee;
        this.object = object;
        this.args = args;
        this.flags = flags;
        this.id = nextID[nextID.length - 1] += 1;
      }
      callNode.prototype = extend(StoreDependent, 'Call');
      callNode.prototype.nodeName = 'Call';
      callNode.prototype.visitInputs = function (visitor) {
        this.control && visitor(this.control);
        this.store && visitor(this.store);
        this.loads && visitArrayInputs(this.loads, visitor);
        visitor(this.callee);
        this.object && visitor(this.object);
        visitArrayInputs(this.args, visitor);
      };
      return callNode;
    }();
  var CallProperty = function () {
      function callPropertyNode(control, store, object, name, args, flags) {
        true;
        true;
        true;
        true;
        true;
        true;
        true;
        this.control = control;
        this.store = store;
        this.loads = undefined;
        this.object = object;
        this.name = name;
        this.args = args;
        this.flags = flags;
        this.id = nextID[nextID.length - 1] += 1;
      }
      callPropertyNode.prototype = extend(StoreDependent, 'CallProperty');
      callPropertyNode.prototype.nodeName = 'CallProperty';
      callPropertyNode.prototype.visitInputs = function (visitor) {
        this.control && visitor(this.control);
        this.store && visitor(this.store);
        this.loads && visitArrayInputs(this.loads, visitor);
        visitor(this.object);
        visitor(this.name);
        visitArrayInputs(this.args, visitor);
      };
      return callPropertyNode;
    }();
  var ASCallProperty = function () {
      function asCallPropertyNode(control, store, object, name, args, flags, isLex) {
        true;
        true;
        true;
        true;
        true;
        true;
        true;
        true;
        this.control = control;
        this.store = store;
        this.loads = undefined;
        this.object = object;
        this.name = name;
        this.args = args;
        this.flags = flags;
        this.isLex = isLex;
        this.id = nextID[nextID.length - 1] += 1;
      }
      asCallPropertyNode.prototype = extend(CallProperty, 'ASCallProperty');
      asCallPropertyNode.prototype.nodeName = 'ASCallProperty';
      asCallPropertyNode.prototype.visitInputs = function (visitor) {
        this.control && visitor(this.control);
        this.store && visitor(this.store);
        this.loads && visitArrayInputs(this.loads, visitor);
        visitor(this.object);
        visitor(this.name);
        visitArrayInputs(this.args, visitor);
      };
      return asCallPropertyNode;
    }();
  var ASCallSuper = function () {
      function asCallSuperNode(control, store, object, name, args, flags, scope) {
        true;
        true;
        true;
        true;
        true;
        true;
        true;
        true;
        this.control = control;
        this.store = store;
        this.loads = undefined;
        this.object = object;
        this.name = name;
        this.args = args;
        this.flags = flags;
        this.scope = scope;
        this.id = nextID[nextID.length - 1] += 1;
      }
      asCallSuperNode.prototype = extend(CallProperty, 'ASCallSuper');
      asCallSuperNode.prototype.nodeName = 'ASCallSuper';
      asCallSuperNode.prototype.visitInputs = function (visitor) {
        this.control && visitor(this.control);
        this.store && visitor(this.store);
        this.loads && visitArrayInputs(this.loads, visitor);
        visitor(this.object);
        visitor(this.name);
        visitArrayInputs(this.args, visitor);
        visitor(this.scope);
      };
      return asCallSuperNode;
    }();
  var New = function () {
      function newNode(control, store, callee, args) {
        true;
        true;
        true;
        true;
        true;
        this.control = control;
        this.store = store;
        this.loads = undefined;
        this.callee = callee;
        this.args = args;
        this.id = nextID[nextID.length - 1] += 1;
      }
      newNode.prototype = extend(StoreDependent, 'New');
      newNode.prototype.nodeName = 'New';
      newNode.prototype.visitInputs = function (visitor) {
        this.control && visitor(this.control);
        this.store && visitor(this.store);
        this.loads && visitArrayInputs(this.loads, visitor);
        visitor(this.callee);
        visitArrayInputs(this.args, visitor);
      };
      return newNode;
    }();
  var ASNew = function () {
      function asNewNode(control, store, callee, args) {
        true;
        true;
        true;
        true;
        true;
        this.control = control;
        this.store = store;
        this.loads = undefined;
        this.callee = callee;
        this.args = args;
        this.id = nextID[nextID.length - 1] += 1;
      }
      asNewNode.prototype = extend(New, 'ASNew');
      asNewNode.prototype.nodeName = 'ASNew';
      asNewNode.prototype.visitInputs = function (visitor) {
        this.control && visitor(this.control);
        this.store && visitor(this.store);
        this.loads && visitArrayInputs(this.loads, visitor);
        visitor(this.callee);
        visitArrayInputs(this.args, visitor);
      };
      return asNewNode;
    }();
  var GetProperty = function () {
      function getPropertyNode(control, store, object, name) {
        true;
        true;
        true;
        true;
        true;
        this.control = control;
        this.store = store;
        this.loads = undefined;
        this.object = object;
        this.name = name;
        this.id = nextID[nextID.length - 1] += 1;
      }
      getPropertyNode.prototype = extend(StoreDependent, 'GetProperty');
      getPropertyNode.prototype.nodeName = 'GetProperty';
      getPropertyNode.prototype.visitInputs = function (visitor) {
        this.control && visitor(this.control);
        this.store && visitor(this.store);
        this.loads && visitArrayInputs(this.loads, visitor);
        visitor(this.object);
        visitor(this.name);
      };
      return getPropertyNode;
    }();
  var ASGetProperty = function () {
      function asGetPropertyNode(control, store, object, name, flags) {
        true;
        true;
        true;
        true;
        true;
        true;
        this.control = control;
        this.store = store;
        this.loads = undefined;
        this.object = object;
        this.name = name;
        this.flags = flags;
        this.id = nextID[nextID.length - 1] += 1;
      }
      asGetPropertyNode.prototype = extend(GetProperty, 'ASGetProperty');
      asGetPropertyNode.prototype.nodeName = 'ASGetProperty';
      asGetPropertyNode.prototype.visitInputs = function (visitor) {
        this.control && visitor(this.control);
        this.store && visitor(this.store);
        this.loads && visitArrayInputs(this.loads, visitor);
        visitor(this.object);
        visitor(this.name);
      };
      return asGetPropertyNode;
    }();
  var ASGetDescendants = function () {
      function asGetDescendantsNode(control, store, object, name) {
        true;
        true;
        true;
        true;
        true;
        this.control = control;
        this.store = store;
        this.loads = undefined;
        this.object = object;
        this.name = name;
        this.id = nextID[nextID.length - 1] += 1;
      }
      asGetDescendantsNode.prototype = extend(GetProperty, 'ASGetDescendants');
      asGetDescendantsNode.prototype.nodeName = 'ASGetDescendants';
      asGetDescendantsNode.prototype.visitInputs = function (visitor) {
        this.control && visitor(this.control);
        this.store && visitor(this.store);
        this.loads && visitArrayInputs(this.loads, visitor);
        visitor(this.object);
        visitor(this.name);
      };
      return asGetDescendantsNode;
    }();
  var ASHasProperty = function () {
      function asHasPropertyNode(control, store, object, name) {
        true;
        true;
        true;
        true;
        true;
        this.control = control;
        this.store = store;
        this.loads = undefined;
        this.object = object;
        this.name = name;
        this.id = nextID[nextID.length - 1] += 1;
      }
      asHasPropertyNode.prototype = extend(GetProperty, 'ASHasProperty');
      asHasPropertyNode.prototype.nodeName = 'ASHasProperty';
      asHasPropertyNode.prototype.visitInputs = function (visitor) {
        this.control && visitor(this.control);
        this.store && visitor(this.store);
        this.loads && visitArrayInputs(this.loads, visitor);
        visitor(this.object);
        visitor(this.name);
      };
      return asHasPropertyNode;
    }();
  var ASGetSlot = function () {
      function asGetSlotNode(control, store, object, name) {
        true;
        true;
        true;
        true;
        true;
        this.control = control;
        this.store = store;
        this.loads = undefined;
        this.object = object;
        this.name = name;
        this.id = nextID[nextID.length - 1] += 1;
      }
      asGetSlotNode.prototype = extend(GetProperty, 'ASGetSlot');
      asGetSlotNode.prototype.nodeName = 'ASGetSlot';
      asGetSlotNode.prototype.visitInputs = function (visitor) {
        this.control && visitor(this.control);
        this.store && visitor(this.store);
        this.loads && visitArrayInputs(this.loads, visitor);
        visitor(this.object);
        visitor(this.name);
      };
      return asGetSlotNode;
    }();
  var ASGetSuper = function () {
      function asGetSuperNode(control, store, object, name, scope) {
        true;
        true;
        true;
        true;
        true;
        true;
        this.control = control;
        this.store = store;
        this.loads = undefined;
        this.object = object;
        this.name = name;
        this.scope = scope;
        this.id = nextID[nextID.length - 1] += 1;
      }
      asGetSuperNode.prototype = extend(GetProperty, 'ASGetSuper');
      asGetSuperNode.prototype.nodeName = 'ASGetSuper';
      asGetSuperNode.prototype.visitInputs = function (visitor) {
        this.control && visitor(this.control);
        this.store && visitor(this.store);
        this.loads && visitArrayInputs(this.loads, visitor);
        visitor(this.object);
        visitor(this.name);
        visitor(this.scope);
      };
      return asGetSuperNode;
    }();
  var SetProperty = function () {
      function setPropertyNode(control, store, object, name, value) {
        true;
        true;
        true;
        true;
        true;
        true;
        this.control = control;
        this.store = store;
        this.loads = undefined;
        this.object = object;
        this.name = name;
        this.value = value;
        this.id = nextID[nextID.length - 1] += 1;
      }
      setPropertyNode.prototype = extend(StoreDependent, 'SetProperty');
      setPropertyNode.prototype.nodeName = 'SetProperty';
      setPropertyNode.prototype.visitInputs = function (visitor) {
        this.control && visitor(this.control);
        this.store && visitor(this.store);
        this.loads && visitArrayInputs(this.loads, visitor);
        visitor(this.object);
        visitor(this.name);
        visitor(this.value);
      };
      return setPropertyNode;
    }();
  var ASSetProperty = function () {
      function asSetPropertyNode(control, store, object, name, value, flags) {
        true;
        true;
        true;
        true;
        true;
        true;
        this.control = control;
        this.store = store;
        this.loads = undefined;
        this.object = object;
        this.name = name;
        this.value = value;
        this.flags = flags;
        this.id = nextID[nextID.length - 1] += 1;
      }
      asSetPropertyNode.prototype = extend(SetProperty, 'ASSetProperty');
      asSetPropertyNode.prototype.nodeName = 'ASSetProperty';
      asSetPropertyNode.prototype.visitInputs = function (visitor) {
        this.control && visitor(this.control);
        this.store && visitor(this.store);
        this.loads && visitArrayInputs(this.loads, visitor);
        visitor(this.object);
        visitor(this.name);
        visitor(this.value);
      };
      return asSetPropertyNode;
    }();
  var ASSetSlot = function () {
      function asSetSlotNode(control, store, object, name, value) {
        true;
        true;
        true;
        true;
        true;
        true;
        this.control = control;
        this.store = store;
        this.loads = undefined;
        this.object = object;
        this.name = name;
        this.value = value;
        this.id = nextID[nextID.length - 1] += 1;
      }
      asSetSlotNode.prototype = extend(SetProperty, 'ASSetSlot');
      asSetSlotNode.prototype.nodeName = 'ASSetSlot';
      asSetSlotNode.prototype.visitInputs = function (visitor) {
        this.control && visitor(this.control);
        this.store && visitor(this.store);
        this.loads && visitArrayInputs(this.loads, visitor);
        visitor(this.object);
        visitor(this.name);
        visitor(this.value);
      };
      return asSetSlotNode;
    }();
  var ASSetSuper = function () {
      function asSetSuperNode(control, store, object, name, value, scope) {
        true;
        true;
        true;
        true;
        true;
        true;
        true;
        this.control = control;
        this.store = store;
        this.loads = undefined;
        this.object = object;
        this.name = name;
        this.value = value;
        this.scope = scope;
        this.id = nextID[nextID.length - 1] += 1;
      }
      asSetSuperNode.prototype = extend(SetProperty, 'ASSetSuper');
      asSetSuperNode.prototype.nodeName = 'ASSetSuper';
      asSetSuperNode.prototype.visitInputs = function (visitor) {
        this.control && visitor(this.control);
        this.store && visitor(this.store);
        this.loads && visitArrayInputs(this.loads, visitor);
        visitor(this.object);
        visitor(this.name);
        visitor(this.value);
        visitor(this.scope);
      };
      return asSetSuperNode;
    }();
  var DeleteProperty = function () {
      function deletePropertyNode(control, store, object, name) {
        true;
        true;
        true;
        true;
        true;
        this.control = control;
        this.store = store;
        this.loads = undefined;
        this.object = object;
        this.name = name;
        this.id = nextID[nextID.length - 1] += 1;
      }
      deletePropertyNode.prototype = extend(StoreDependent, 'DeleteProperty');
      deletePropertyNode.prototype.nodeName = 'DeleteProperty';
      deletePropertyNode.prototype.visitInputs = function (visitor) {
        this.control && visitor(this.control);
        this.store && visitor(this.store);
        this.loads && visitArrayInputs(this.loads, visitor);
        visitor(this.object);
        visitor(this.name);
      };
      return deletePropertyNode;
    }();
  var ASDeleteProperty = function () {
      function asDeletePropertyNode(control, store, object, name) {
        true;
        true;
        true;
        true;
        true;
        this.control = control;
        this.store = store;
        this.loads = undefined;
        this.object = object;
        this.name = name;
        this.id = nextID[nextID.length - 1] += 1;
      }
      asDeletePropertyNode.prototype = extend(DeleteProperty, 'ASDeleteProperty');
      asDeletePropertyNode.prototype.nodeName = 'ASDeleteProperty';
      asDeletePropertyNode.prototype.visitInputs = function (visitor) {
        this.control && visitor(this.control);
        this.store && visitor(this.store);
        this.loads && visitArrayInputs(this.loads, visitor);
        visitor(this.object);
        visitor(this.name);
      };
      return asDeletePropertyNode;
    }();
  var ASFindProperty = function () {
      function asFindPropertyNode(control, store, scope, name, domain, strict) {
        true;
        true;
        true;
        true;
        true;
        true;
        this.control = control;
        this.store = store;
        this.loads = undefined;
        this.scope = scope;
        this.name = name;
        this.domain = domain;
        this.strict = strict;
        this.id = nextID[nextID.length - 1] += 1;
      }
      asFindPropertyNode.prototype = extend(StoreDependent, 'ASFindProperty');
      asFindPropertyNode.prototype.nodeName = 'ASFindProperty';
      asFindPropertyNode.prototype.visitInputs = function (visitor) {
        this.control && visitor(this.control);
        this.store && visitor(this.store);
        this.loads && visitArrayInputs(this.loads, visitor);
        visitor(this.scope);
        visitor(this.name);
        visitor(this.domain);
      };
      return asFindPropertyNode;
    }();
  var Store = function () {
      function storeNode() {
        true;
        this.id = nextID[nextID.length - 1] += 1;
      }
      storeNode.prototype = extend(Value, 'Store');
      storeNode.prototype.nodeName = 'Store';
      storeNode.prototype.visitInputs = function (visitor) {
      };
      return storeNode;
    }();
  var Phi = function () {
      function phiNode(control, value) {
        true;
        true;
        this.control = control;
        this.args = value ? [
          value
        ] : [];
        this.id = nextID[nextID.length - 1] += 1;
      }
      phiNode.prototype = extend(Value, 'Phi');
      phiNode.prototype.nodeName = 'Phi';
      phiNode.prototype.visitInputs = function (visitor) {
        this.control && visitor(this.control);
        visitArrayInputs(this.args, visitor);
      };
      return phiNode;
    }();
  var Variable = function () {
      function variableNode(name) {
        true;
        this.name = name;
        this.id = nextID[nextID.length - 1] += 1;
      }
      variableNode.prototype = extend(Value, 'Variable');
      variableNode.prototype.nodeName = 'Variable';
      variableNode.prototype.visitInputs = function (visitor) {
      };
      return variableNode;
    }();
  var Copy = function () {
      function copyNode(argument) {
        true;
        this.argument = argument;
        this.id = nextID[nextID.length - 1] += 1;
      }
      copyNode.prototype = extend(Value, 'Copy');
      copyNode.prototype.nodeName = 'Copy';
      copyNode.prototype.visitInputs = function (visitor) {
        visitor(this.argument);
      };
      return copyNode;
    }();
  var Move = function () {
      function moveNode(to, from) {
        true;
        this.to = to;
        this.from = from;
        this.id = nextID[nextID.length - 1] += 1;
      }
      moveNode.prototype = extend(Value, 'Move');
      moveNode.prototype.nodeName = 'Move';
      moveNode.prototype.visitInputs = function (visitor) {
        visitor(this.to);
        visitor(this.from);
      };
      return moveNode;
    }();
  var Projection = function () {
      function projectionNode(argument, type, selector) {
        true;
        this.argument = argument;
        this.type = type;
        this.selector = selector;
        this.id = nextID[nextID.length - 1] += 1;
      }
      projectionNode.prototype = extend(Value, 'Projection');
      projectionNode.prototype.nodeName = 'Projection';
      projectionNode.prototype.visitInputs = function (visitor) {
        visitor(this.argument);
      };
      return projectionNode;
    }();
  var Latch = function () {
      function latchNode(control, condition, left, right) {
        true;
        true;
        this.control = control;
        this.condition = condition;
        this.left = left;
        this.right = right;
        this.id = nextID[nextID.length - 1] += 1;
      }
      latchNode.prototype = extend(Value, 'Latch');
      latchNode.prototype.nodeName = 'Latch';
      latchNode.prototype.visitInputs = function (visitor) {
        this.control && visitor(this.control);
        visitor(this.condition);
        visitor(this.left);
        visitor(this.right);
      };
      return latchNode;
    }();
  var Binary = function () {
      function binaryNode(operator, left, right) {
        true;
        this.operator = operator;
        this.left = left;
        this.right = right;
        this.id = nextID[nextID.length - 1] += 1;
      }
      binaryNode.prototype = extend(Value, 'Binary');
      binaryNode.prototype.nodeName = 'Binary';
      binaryNode.prototype.visitInputs = function (visitor) {
        visitor(this.left);
        visitor(this.right);
      };
      return binaryNode;
    }();
  var Unary = function () {
      function unaryNode(operator, argument) {
        true;
        this.operator = operator;
        this.argument = argument;
        this.id = nextID[nextID.length - 1] += 1;
      }
      unaryNode.prototype = extend(Value, 'Unary');
      unaryNode.prototype.nodeName = 'Unary';
      unaryNode.prototype.visitInputs = function (visitor) {
        visitor(this.argument);
      };
      return unaryNode;
    }();
  var Constant = function () {
      function constantNode(value) {
        true;
        this.value = value;
        this.id = nextID[nextID.length - 1] += 1;
      }
      constantNode.prototype = extend(Value, 'Constant');
      constantNode.prototype.nodeName = 'Constant';
      constantNode.prototype.visitInputs = function (visitor) {
      };
      return constantNode;
    }();
  var GlobalProperty = function () {
      function globalPropertyNode(name) {
        true;
        this.name = name;
        this.id = nextID[nextID.length - 1] += 1;
      }
      globalPropertyNode.prototype = extend(Value, 'GlobalProperty');
      globalPropertyNode.prototype.nodeName = 'GlobalProperty';
      globalPropertyNode.prototype.visitInputs = function (visitor) {
      };
      return globalPropertyNode;
    }();
  var This = function () {
      function thisNode(control) {
        true;
        true;
        this.control = control;
        this.id = nextID[nextID.length - 1] += 1;
      }
      thisNode.prototype = extend(Value, 'This');
      thisNode.prototype.nodeName = 'This';
      thisNode.prototype.visitInputs = function (visitor) {
        visitor(this.control);
      };
      return thisNode;
    }();
  var Throw = function () {
      function throwNode(control, argument) {
        true;
        true;
        this.control = control;
        this.argument = argument;
        this.id = nextID[nextID.length - 1] += 1;
      }
      throwNode.prototype = extend(Value, 'Throw');
      throwNode.prototype.nodeName = 'Throw';
      throwNode.prototype.visitInputs = function (visitor) {
        visitor(this.control);
        visitor(this.argument);
      };
      return throwNode;
    }();
  var Arguments = function () {
      function argumentsNode(control) {
        true;
        true;
        this.control = control;
        this.id = nextID[nextID.length - 1] += 1;
      }
      argumentsNode.prototype = extend(Value, 'Arguments');
      argumentsNode.prototype.nodeName = 'Arguments';
      argumentsNode.prototype.visitInputs = function (visitor) {
        visitor(this.control);
      };
      return argumentsNode;
    }();
  var Parameter = function () {
      function parameterNode(control, index, name) {
        true;
        true;
        this.control = control;
        this.index = index;
        this.name = name;
        this.id = nextID[nextID.length - 1] += 1;
      }
      parameterNode.prototype = extend(Value, 'Parameter');
      parameterNode.prototype.nodeName = 'Parameter';
      parameterNode.prototype.visitInputs = function (visitor) {
        visitor(this.control);
      };
      return parameterNode;
    }();
  var NewArray = function () {
      function newArrayNode(control, elements) {
        true;
        true;
        this.control = control;
        this.elements = elements;
        this.id = nextID[nextID.length - 1] += 1;
      }
      newArrayNode.prototype = extend(Value, 'NewArray');
      newArrayNode.prototype.nodeName = 'NewArray';
      newArrayNode.prototype.visitInputs = function (visitor) {
        visitor(this.control);
        visitArrayInputs(this.elements, visitor);
      };
      return newArrayNode;
    }();
  var NewObject = function () {
      function newObjectNode(control, properties) {
        true;
        true;
        this.control = control;
        this.properties = properties;
        this.id = nextID[nextID.length - 1] += 1;
      }
      newObjectNode.prototype = extend(Value, 'NewObject');
      newObjectNode.prototype.nodeName = 'NewObject';
      newObjectNode.prototype.visitInputs = function (visitor) {
        visitor(this.control);
        visitArrayInputs(this.properties, visitor);
      };
      return newObjectNode;
    }();
  var KeyValuePair = function () {
      function keyValuePairNode(key, value) {
        true;
        this.key = key;
        this.value = value;
        this.id = nextID[nextID.length - 1] += 1;
      }
      keyValuePairNode.prototype = extend(Value, 'KeyValuePair');
      keyValuePairNode.prototype.nodeName = 'KeyValuePair';
      keyValuePairNode.prototype.visitInputs = function (visitor) {
        visitor(this.key);
        visitor(this.value);
      };
      return keyValuePairNode;
    }();
  var ASScope = function () {
      function asScopeNode(parent, object, isWith) {
        true;
        this.parent = parent;
        this.object = object;
        this.isWith = isWith;
        this.id = nextID[nextID.length - 1] += 1;
      }
      asScopeNode.prototype = extend(Value, 'ASScope');
      asScopeNode.prototype.nodeName = 'ASScope';
      asScopeNode.prototype.visitInputs = function (visitor) {
        visitor(this.parent);
        visitor(this.object);
      };
      return asScopeNode;
    }();
  var ASGlobal = function () {
      function asGlobalNode(control, scope) {
        true;
        true;
        true;
        this.control = control;
        this.scope = scope;
        this.id = nextID[nextID.length - 1] += 1;
      }
      asGlobalNode.prototype = extend(Value, 'ASGlobal');
      asGlobalNode.prototype.nodeName = 'ASGlobal';
      asGlobalNode.prototype.visitInputs = function (visitor) {
        this.control && visitor(this.control);
        visitor(this.scope);
      };
      return asGlobalNode;
    }();
  var ASNewActivation = function () {
      function asNewActivationNode(methodInfo) {
        true;
        this.methodInfo = methodInfo;
        this.id = nextID[nextID.length - 1] += 1;
      }
      asNewActivationNode.prototype = extend(Value, 'ASNewActivation');
      asNewActivationNode.prototype.nodeName = 'ASNewActivation';
      asNewActivationNode.prototype.visitInputs = function (visitor) {
      };
      return asNewActivationNode;
    }();
  var ASMultiname = function () {
      function asMultinameNode(namespaces, name, flags) {
        true;
        this.namespaces = namespaces;
        this.name = name;
        this.flags = flags;
        this.id = nextID[nextID.length - 1] += 1;
      }
      asMultinameNode.prototype = extend(Value, 'ASMultiname');
      asMultinameNode.prototype.nodeName = 'ASMultiname';
      asMultinameNode.prototype.visitInputs = function (visitor) {
        visitor(this.namespaces);
        visitor(this.name);
      };
      return asMultinameNode;
    }();
  function node() {
    this.id = nextID[nextID.length - 1] += 1;
  }
  Node.startNumbering = function () {
    nextID.push(0);
  };
  Node.stopNumbering = function () {
    nextID.pop();
  };
  Node.prototype.toString = function (brief) {
    if (brief) {
      return nameOf(this);
    }
    var inputs = [];
    this.visitInputs(function (input) {
      inputs.push(nameOf(input));
    });
    var str = nameOf(this) + ' = ' + this.nodeName.toUpperCase();
    if (this.toStringDetails) {
      str += ' ' + this.toStringDetails();
    }
    if (inputs.length) {
      str += ' ' + inputs.join(', ');
    }
    return str;
  };
  Node.prototype.visitInputsNoConstants = function visitInputs(visitor) {
    this.visitInputs(function (node) {
      if (isConstant(node)) {
        return;
      }
      visitor(node);
    });
  };
  Node.prototype.replaceInput = function (oldInput, newInput) {
    var count = 0;
    for (var k in this) {
      var v = this[k];
      if (v instanceof Node) {
        if (v === oldInput) {
          this[k] = newInput;
          count++;
        }
      }
      if (v instanceof Array) {
        count += v.replace(oldInput, newInput);
      }
    }
    return count;
  };
  Projection.Type = {
    CASE: 'case',
    TRUE: 'true',
    FALSE: 'false',
    STORE: 'store',
    SCOPE: 'scope'
  };
  Projection.prototype.project = function () {
    return this.argument;
  };
  Phi.prototype.seal = function seal() {
    this.sealed = true;
  };
  Phi.prototype.pushValue = function pushValue(x) {
    true;
    true;
    this.args.push(x);
  };
  KeyValuePair.prototype.mustFloat = true;
  ASMultiname.prototype.mustFloat = true;
  ASMultiname.prototype.isAttribute = function () {
    return this.flags & 1;
  };
  var Flags = {
      INDEXED: 1,
      RESOLVED: 2,
      PRISTINE: 4,
      IS_METHOD: 8
    };
  var Operator = function () {
      var map = {};
      function operator(name, evaluate, binary) {
        this.name = name;
        this.binary = binary;
        this.evaluate = evaluate;
        map[name] = this;
      }
      operator.ADD = new operator('+', function (l, r) {
        return l + r;
      }, true);
      operator.SUB = new operator('-', function (l, r) {
        return l - r;
      }, true);
      operator.MUL = new operator('*', function (l, r) {
        return l * r;
      }, true);
      operator.DIV = new operator('/', function (l, r) {
        return l / r;
      }, true);
      operator.MOD = new operator('%', function (l, r) {
        return l % r;
      }, true);
      operator.AND = new operator('&', function (l, r) {
        return l & r;
      }, true);
      operator.OR = new operator('|', function (l, r) {
        return l | r;
      }, true);
      operator.XOR = new operator('^', function (l, r) {
        return l ^ r;
      }, true);
      operator.LSH = new operator('<<', function (l, r) {
        return l << r;
      }, true);
      operator.RSH = new operator('>>', function (l, r) {
        return l >> r;
      }, true);
      operator.URSH = new operator('>>>', function (l, r) {
        return l >>> r;
      }, true);
      operator.SEQ = new operator('===', function (l, r) {
        return l === r;
      }, true);
      operator.SNE = new operator('!==', function (l, r) {
        return l !== r;
      }, true);
      operator.EQ = new operator('==', function (l, r) {
        return l == r;
      }, true);
      operator.NE = new operator('!=', function (l, r) {
        return l != r;
      }, true);
      operator.LE = new operator('<=', function (l, r) {
        return l <= r;
      }, true);
      operator.GT = new operator('>', function (l, r) {
        return l > r;
      }, true);
      operator.LT = new operator('<', function (l, r) {
        return l < r;
      }, true);
      operator.GE = new operator('>=', function (l, r) {
        return l >= r;
      }, true);
      operator.BITWISE_NOT = new operator('~', function (a) {
        return ~a;
      }, false);
      operator.PLUS = new operator('+', function (a) {
        return +a;
      }, false);
      operator.NEG = new operator('-', function (a) {
        return -a;
      }, false);
      operator.TYPE_OF = new operator('typeof', function (a) {
        return typeof a;
      }, false);
      operator.TRUE = new operator('!!', function (a) {
        return !(!a);
      }, false);
      operator.FALSE = new operator('!', function (a) {
        return !a;
      }, false);
      operator.AS_ADD = new operator('+', function (l, r) {
        if (typeof l === 'string' || typeof r === 'string') {
          return String(l) + String(r);
        }
        return l + r;
      }, true);
      function linkOpposites(a, b) {
        a.not = b;
        b.not = a;
      }
      linkOpposites(operator.SEQ, operator.SNE);
      linkOpposites(operator.EQ, operator.NE);
      linkOpposites(operator.TRUE, operator.FALSE);
      operator.fromName = function fromName(name) {
        return map[name];
      };
      operator.prototype.isBinary = function isBinary() {
        return this.binary;
      };
      operator.prototype.toString = function toString() {
        return this.name;
      };
      return operator;
    }();
  function extend(c, name) {
    true;
    return Object.create(c.prototype, {
      nodeName: {
        value: name
      }
    });
  }
  function nameOf(o) {
    var useColors = false;
    var result;
    if (o instanceof Constant) {
      if (o.value instanceof Multiname) {
        return o.value.name;
      }
      return o.value;
    } else if (o instanceof Variable) {
      return o.name;
    } else if (o instanceof Phi) {
      return result = '|' + o.id + '|', useColors ? PURPLE + result + ENDC : result;
    } else if (o instanceof Control) {
      return result = '{' + o.id + '}', useColors ? RED + result + ENDC : result;
    } else if (o instanceof Projection) {
      if (o.type === Projection.Type.STORE) {
        return result = '[' + o.id + '->' + o.argument.id + ']', useColors ? YELLOW + result + ENDC : result;
      }
      return result = '(' + o.id + ')', useColors ? GREEN + result + ENDC : result;
    } else if (o instanceof Value) {
      return result = '(' + o.id + ')', useColors ? GREEN + result + ENDC : result;
    } else if (o instanceof Node) {
      return o.id;
    }
    unexpected(o + ' ' + typeof o);
  }
  function toID(node) {
    return node.id;
  }
  function visitArrayInputs(array, visitor) {
    for (var i = 0; i < array.length; i++) {
      visitor(array[i]);
    }
  }
  function visitNothing() {
  }
  function isNotPhi(phi) {
    return !isPhi(phi);
  }
  function isPhi(phi) {
    return phi instanceof Phi;
  }
  function isScope(scope) {
    return isPhi(scope) || scope instanceof ASScope || isProjection(scope, Projection.Type.SCOPE);
  }
  function isMultinameConstant(node) {
    return node instanceof Constant && node.value instanceof Multiname;
  }
  function isMultiname(name) {
    return isMultinameConstant(name) || name instanceof ASMultiname;
  }
  function isStore(store) {
    return isPhi(store) || store instanceof Store || isProjection(store, Projection.Type.STORE);
  }
  function isConstant(constant) {
    return constant instanceof Constant;
  }
  function isBoolean(boolean) {
    return boolean === true || boolean === false;
  }
  function isInteger(integer) {
    return integer | 0 === integer;
  }
  function isArray(array) {
    return array instanceof Array;
  }
  function isControlOrNull(control) {
    return isControl(control) || control === null;
  }
  function isStoreOrNull(store) {
    return isStore(store) || store === null;
  }
  function isControl(control) {
    return control instanceof Control;
  }
  function isValueOrNull(value) {
    return isValue(value) || value === null;
  }
  function isValue(value) {
    return value instanceof Value;
  }
  function isProjection(node, type) {
    return node instanceof Projection && (!type || node.type === type);
  }
  var Null = new Constant(null);
  var Undefined = new Constant(undefined);
  Undefined.toString = function () {
    return '_';
  };
  var Block = function () {
      function block(id, start, end) {
        if (start) {
          true;
        }
        this.region = start;
        this.id = id;
        this.successors = [];
        this.predecessors = [];
        this.nodes = [
          start,
          end
        ];
      }
      block.prototype.pushSuccessorAt = function pushSuccessor(successor, index, pushPredecessor) {
        true;
        true;
        this.successors[index] = successor;
        if (pushPredecessor) {
          successor.pushPredecessor(this);
        }
      };
      block.prototype.pushSuccessor = function pushSuccessor(successor, pushPredecessor) {
        true;
        this.successors.push(successor);
        if (pushPredecessor) {
          successor.pushPredecessor(this);
        }
      };
      block.prototype.pushPredecessor = function pushPredecessor(predecessor) {
        true;
        this.predecessors.push(predecessor);
      };
      block.prototype.visitNodes = function (fn) {
        var nodes = this.nodes;
        for (var i = 0, j = nodes.length; i < j; i++) {
          fn(nodes[i]);
        }
      };
      block.prototype.visitSuccessors = function (fn) {
        var successors = this.successors;
        for (var i = 0, j = successors.length; i < j; i++) {
          fn(successors[i]);
        }
      };
      block.prototype.visitPredecessors = function (fn) {
        var predecessors = this.predecessors;
        for (var i = 0, j = predecessors.length; i < j; i++) {
          fn(predecessors[i]);
        }
      };
      block.prototype.append = function (node) {
        true;
        true;
        true;
        true;
        if (node.mustFloat) {
          return;
        }
        this.nodes.splice(this.nodes.length - 1, 0, node);
      };
      block.prototype.toString = function () {
        return 'B' + this.id + (this.name ? ' (' + this.name + ')' : '');
      };
      block.prototype.trace = function (writer) {
        writer.writeLn(this);
      };
      return block;
    }();
  var DFG = function () {
      function constructor(exit) {
        this.exit = exit;
      }
      constructor.prototype.buildCFG = function () {
        return CFG.fromDFG(this);
      };
      function preOrderDepthFirstSearch(root, visitChildren, pre) {
        var visited = [];
        var worklist = [
            root
          ];
        var push = worklist.push.bind(worklist);
        var node;
        while (node = worklist.pop()) {
          if (visited[node.id] === 1) {
            continue;
          }
          visited[node.id] = 1;
          pre(node);
          worklist.push(node);
          visitChildren(node, push);
        }
      }
      function postOrderDepthFirstSearch(root, visitChildren, post) {
        var ONE_TIME = 1, MANY_TIMES = 2;
        var visited = [];
        var worklist = [
            root
          ];
        function visitChild(child) {
          if (!visited[child.id]) {
            worklist.push(child);
          }
        }
        var node;
        while (node = worklist.top()) {
          if (visited[node.id]) {
            if (visited[node.id] === ONE_TIME) {
              visited[node.id] = MANY_TIMES;
              post(node);
            }
            worklist.pop();
            continue;
          }
          visited[node.id] = ONE_TIME;
          visitChildren(node, visitChild);
        }
      }
      constructor.prototype.forEachInPreOrderDepthFirstSearch = function forEachInPreOrderDepthFirstSearch(visitor) {
        var visited = new Array(1024);
        var worklist = [
            this.exit
          ];
        function push(node) {
          if (isConstant(node)) {
            return;
          }
          true;
          worklist.push(node);
        }
        var node;
        while (node = worklist.pop()) {
          if (visited[node.id]) {
            continue;
          }
          visited[node.id] = 1;
          visitor && visitor(node);
          worklist.push(node);
          node.visitInputs(push);
        }
      };
      constructor.prototype.forEach = function forEach(visitor, postOrder) {
        var search = postOrder ? postOrderDepthFirstSearch : preOrderDepthFirstSearch;
        search(this.exit, function (node, v) {
          node.visitInputsNoConstants(v);
        }, visitor);
      };
      constructor.prototype.traceMetrics = function (writer) {
        var counter = new metrics.Counter(true);
        preOrderDepthFirstSearch(this.exit, function (node, visitor) {
          node.visitInputsNoConstants(visitor);
        }, function (node) {
          counter.count(node.nodeName);
        });
        counter.trace(writer);
      };
      constructor.prototype.trace = function (writer) {
        var nodes = [];
        var visited = {};
        function colorOf(node) {
          if (node instanceof Control) {
            return 'yellow';
          } else if (node instanceof Phi) {
            return 'purple';
          } else if (node instanceof Value) {
            return 'green';
          }
          return 'white';
        }
        var blocks = [];
        function followProjection(node) {
          return node instanceof Projection ? node.project() : node;
        }
        function next(node) {
          node = followProjection(node);
          if (!visited[node.id]) {
            visited[node.id] = true;
            if (node.block) {
              blocks.push(node.block);
            }
            nodes.push(node);
            node.visitInputsNoConstants(next);
          }
        }
        next(this.exit);
        writer.writeLn('');
        writer.enter('digraph DFG {');
        writer.writeLn('graph [bgcolor = gray10];');
        writer.writeLn('edge [color = white];');
        writer.writeLn('node [shape = box, fontname = Consolas, fontsize = 11, color = white, fontcolor = white];');
        writer.writeLn('rankdir = BT;');
        function writeNode(node) {
          writer.writeLn('N' + node.id + ' [label = "' + node.toString() + '", color = "' + colorOf(node) + '"];');
        }
        function defineNode(node) {
          writer.writeLn('N' + node.id + ';');
        }
        blocks.forEach(function (block) {
          writer.enter('subgraph cluster' + block.nodes[0].id + ' { bgcolor = gray20;');
          block.visitNodes(function (node) {
            defineNode(followProjection(node));
          });
          writer.leave('}');
        });
        nodes.forEach(writeNode);
        nodes.forEach(function (node) {
          node.visitInputsNoConstants(function (input) {
            input = followProjection(input);
            writer.writeLn('N' + node.id + ' -> ' + 'N' + input.id + ' [color=' + colorOf(input) + '];');
          });
        });
        writer.leave('}');
        writer.writeLn('');
      };
      return constructor;
    }();
  var CFG = function () {
      function constructor() {
        this.nextBlockID = 0;
        this.blocks = [];
        this.exit;
        this.root;
      }
      constructor.fromDFG = function fromDFG(dfg) {
        var cfg = new CFG();
        true;
        cfg.dfg = dfg;
        var visited = [];
        function buildEnd(end) {
          if (end instanceof Projection) {
            end = end.project();
          }
          true;
          if (visited[end.id]) {
            return;
          }
          visited[end.id] = true;
          var start = end.control;
          if (!(start instanceof Region)) {
            start = end.control = new Region(start);
          }
          var block = start.block = cfg.buildBlock(start, end);
          if (start instanceof Start) {
            cfg.root = block;
          }
          for (var i = 0; i < start.predecessors.length; i++) {
            var c = start.predecessors[i];
            var d;
            var trueProjection = false;
            if (c instanceof Projection) {
              d = c.project();
              trueProjection = c.type === Projection.Type.TRUE;
            } else {
              d = c;
            }
            if (d instanceof Region) {
              d = new Jump(c);
              d = new Projection(d, Projection.Type.TRUE);
              start.predecessors[i] = d;
              d = d.project();
              trueProjection = true;
            }
            buildEnd(d);
            var controlBlock = d.control.block;
            if (d instanceof Switch) {
              true;
              controlBlock.pushSuccessorAt(block, c.selector.value, true);
            } else if (trueProjection && controlBlock.successors.length > 0) {
              controlBlock.pushSuccessor(block, true);
              controlBlock.hasFlippedSuccessors = true;
            } else {
              controlBlock.pushSuccessor(block, true);
            }
          }
        }
        buildEnd(dfg.exit);
        cfg.splitCriticalEdges();
        cfg.exit = dfg.exit.control.block;
        cfg.computeDominators(true);
        return cfg;
      };
      constructor.prototype.buildRootAndExit = function buildRootAndExit() {
        true;
        if (this.blocks[0].predecessors.length > 0) {
          this.root = new Block(this.nextBlockID++);
          this.blocks.push(this.root);
          this.root.pushSuccessor(this.blocks[0], true);
        } else {
          this.root = this.blocks[0];
        }
        var exitBlocks = [];
        for (var i = 0; i < this.blocks.length; i++) {
          var block = this.blocks[i];
          if (block.successors.length === 0) {
            exitBlocks.push(block);
          }
        }
        if (exitBlocks.length === 0) {
          unexpected('Must have an exit block.');
        } else if (exitBlocks.length === 1 && exitBlocks[0] !== this.root) {
          this.exit = exitBlocks[0];
        } else {
          this.exit = new Block(this.nextBlockID++);
          this.blocks.push(this.exit);
          for (var i = 0; i < exitBlocks.length; i++) {
            exitBlocks[i].pushSuccessor(this.exit, true);
          }
        }
        true;
        true;
      };
      constructor.prototype.fromString = function (list, rootName) {
        var cfg = this;
        var names = cfg.blockNames || (cfg.blockNames = {});
        var blocks = cfg.blocks;
        var sets = list.replace(/\ /g, '').split(',');
        sets.forEach(function (set) {
          var edgeList = set.split('->');
          var last = null;
          for (var i = 0; i < edgeList.length; i++) {
            var next = edgeList[i];
            if (last) {
              buildEdge(last, next);
            } else {
              buildBlock(next);
            }
            last = next;
          }
        });
        function buildBlock(name) {
          var block = names[name];
          if (block) {
            return block;
          }
          names[name] = block = new Block(cfg.nextBlockID++);
          block.name = name;
          blocks.push(block);
          return block;
        }
        function buildEdge(from, to) {
          buildBlock(from).pushSuccessor(buildBlock(to), true);
        }
        true;
        this.root = names[rootName];
      };
      constructor.prototype.buildBlock = function (start, end) {
        var block = new Block(this.nextBlockID++, start, end);
        this.blocks.push(block);
        return block;
      };
      constructor.prototype.createBlockSet = function () {
        if (!this.setConstructor) {
          this.setConstructor = BitSetFunctor(this.blocks.length);
        }
        return new this.setConstructor();
      };
      constructor.prototype.computeReversePostOrder = function computeReversePostOrder() {
        if (this.order) {
          return this.order;
        }
        var order = this.order = [];
        this.depthFirstSearch(null, order.push.bind(order));
        order.reverse();
        for (var i = 0; i < order.length; i++) {
          order[i].rpo = i;
        }
        return order;
      };
      constructor.prototype.depthFirstSearch = function depthFirstSearch(preFn, postFn) {
        var visited = this.createBlockSet();
        function visit(node) {
          visited.set(node.id);
          if (preFn)
            preFn(node);
          var successors = node.successors;
          for (var i = 0, j = successors.length; i < j; i++) {
            var s = successors[i];
            if (!visited.get(s.id)) {
              visit(s);
            }
          }
          if (postFn)
            postFn(node);
        }
        visit(this.root);
      };
      constructor.prototype.computeDominators = function (apply) {
        true;
        var dom = new Int32Array(this.blocks.length);
        for (var i = 0; i < dom.length; i++) {
          dom[i] = -1;
        }
        var map = this.createBlockSet();
        function computeCommonDominator(a, b) {
          map.clearAll();
          while (a >= 0) {
            map.set(a);
            a = dom[a];
          }
          while (b >= 0 && !map.get(b)) {
            b = dom[b];
          }
          return b;
        }
        function computeDominator(blockID, parentID) {
          if (dom[blockID] < 0) {
            dom[blockID] = parentID;
          } else {
            dom[blockID] = computeCommonDominator(dom[blockID], parentID);
          }
        }
        this.depthFirstSearch(function visit(block) {
          var s = block.successors;
          for (var i = 0, j = s.length; i < j; i++) {
            computeDominator(s[i].id, block.id);
          }
        });
        if (apply) {
          for (var i = 0, j = this.blocks.length; i < j; i++) {
            this.blocks[i].dominator = this.blocks[dom[i]];
          }
          function computeDominatorDepth(block) {
            var dominatorDepth;
            if (block.dominatorDepth !== undefined) {
              return block.dominatorDepth;
            } else if (!block.dominator) {
              dominatorDepth = 0;
            } else {
              dominatorDepth = computeDominatorDepth(block.dominator) + 1;
            }
            return block.dominatorDepth = dominatorDepth;
          }
          for (var i = 0, j = this.blocks.length; i < j; i++) {
            computeDominatorDepth(this.blocks[i]);
          }
        }
        return dom;
      };
      constructor.prototype.computeLoops = function computeLoops() {
        var active = this.createBlockSet();
        var visited = this.createBlockSet();
        var nextLoop = 0;
        function makeLoopHeader(block) {
          if (!block.isLoopHeader) {
            block.isLoopHeader = true;
            block.loops = 1 << nextLoop;
            nextLoop += 1;
          }
        }
        function visit(block) {
          if (visited.get(block.id)) {
            if (active.get(block.id)) {
              makeLoopHeader(block);
            }
            return block.loops;
          }
          visited.set(block.id);
          active.set(block.id);
          var loops = 0;
          for (var i = 0, j = block.successors.length; i < j; i++) {
            loops |= visit(block.successors[i]);
          }
          if (block.isLoopHeader) {
            loops &= ~block.loops;
          }
          block.loops = loops;
          active.clear(block.id);
          return loops;
        }
        var loop = visit(this.root);
      };
      function followProjection(node) {
        return node instanceof Projection ? node.project() : node;
      }
      var Uses = function () {
          function constructor() {
            this.entries = [];
          }
          constructor.prototype.addUse = function addUse(def, use) {
            var entry = this.entries[def.id];
            if (!entry) {
              entry = this.entries[def.id] = {
                def: def,
                uses: []
              };
            }
            entry.uses.pushUnique(use);
          };
          constructor.prototype.trace = function (writer) {
            writer.enter('> Uses');
            this.entries.forEach(function (entry) {
              writer.writeLn(entry.def.id + ' -> [' + entry.uses.map(toID).join(', ') + '] ' + entry.def);
            });
            writer.leave('<');
          };
          constructor.prototype.replace = function (def, value) {
            var entry = this.entries[def.id];
            if (entry.uses.length === 0) {
              return false;
            }
            var count = 0;
            entry.uses.forEach(function (use) {
              count += use.replaceInput(def, value);
            });
            true;
            entry.uses = [];
            return true;
          };
          function updateUses(def, value) {
            debug && writer.writeLn('Update ' + def + ' with ' + value);
            var entry = useEntries[def.id];
            if (entry.uses.length === 0) {
              return false;
            }
            debug && writer.writeLn('Replacing: ' + def.id + ' in [' + entry.uses.map(toID).join(', ') + '] with ' + value.id);
            var count = 0;
            entry.uses.forEach(function (use) {
              count += use.replaceInput(def, value);
            });
            true;
            entry.uses = [];
            return true;
          }
          return constructor;
        }();
      constructor.prototype.computeUses = function computeUses() {
        Timer.start('computeUses');
        var writer = debug && new IndentingWriter();
        debug && writer.enter('> Compute Uses');
        var dfg = this.dfg;
        var uses = new Uses();
        dfg.forEachInPreOrderDepthFirstSearch(function (use) {
          use.visitInputs(function (def) {
            uses.addUse(def, use);
          });
        });
        if (debug) {
          writer.enter('> Uses');
          uses.entries.forEach(function (entry) {
            writer.writeLn(entry.def.id + ' -> [' + entry.uses.map(toID).join(', ') + '] ' + entry.def);
          });
          writer.leave('<');
          writer.leave('<');
        }
        Timer.stop();
        return uses;
      };
      constructor.prototype.verify = function verify() {
        var writer = debug && new IndentingWriter();
        debug && writer.enter('> Verify');
        var order = this.computeReversePostOrder();
        order.forEach(function (block) {
          if (block.phis) {
            block.phis.forEach(function (phi) {
              true;
              true;
            });
          }
        });
        debug && writer.leave('<');
      };
      constructor.prototype.optimizePhis = function optimizePhis() {
        var writer = debug && new IndentingWriter();
        debug && writer.enter('> Optimize Phis');
        var phis = [];
        var useEntries = this.computeUses().entries;
        useEntries.forEach(function (entry) {
          if (isPhi(entry.def)) {
            phis.push(entry.def);
          }
        });
        debug && writer.writeLn('Trying to optimize ' + phis.length + ' phis.');
        function updateUses(def, value) {
          debug && writer.writeLn('Update ' + def + ' with ' + value);
          var entry = useEntries[def.id];
          if (entry.uses.length === 0) {
            return false;
          }
          debug && writer.writeLn('Replacing: ' + def.id + ' in [' + entry.uses.map(toID).join(', ') + '] with ' + value.id);
          var count = 0;
          var entryUses = entry.uses;
          for (var i = 0, j = entryUses.length; i < j; i++) {
            count += entryUses[i].replaceInput(def, value);
          }
          true;
          entry.uses = [];
          return true;
        }
        function simplify(phi, args) {
          args = args.unique();
          if (args.length === 1) {
            return args[0];
          } else {
            if (args.length === 2) {
              if (args[0] === phi) {
                return args[1];
              } else if (args[1] === phi) {
                return args[0];
              }
              return phi;
            }
          }
          return phi;
        }
        var count = 0;
        var iterations = 0;
        var changed = true;
        while (changed) {
          iterations++;
          changed = false;
          phis.forEach(function (phi) {
            var value = simplify(phi, phi.args);
            if (value !== phi) {
              if (updateUses(phi, value)) {
                changed = true;
                count++;
              }
            }
          });
        }
        if (debug) {
          writer.writeLn('Simplified ' + count + ' phis, in ' + iterations + ' iterations.');
          writer.leave('<');
        }
      };
      constructor.prototype.splitCriticalEdges = function splitCriticalEdges() {
        var writer = debug && new IndentingWriter();
        var blocks = this.blocks;
        var criticalEdges = [];
        debug && writer.enter('> Splitting Critical Edges');
        for (var i = 0; i < blocks.length; i++) {
          var successors = blocks[i].successors;
          if (successors.length > 1) {
            for (var j = 0; j < successors.length; j++) {
              if (successors[j].predecessors.length > 1) {
                criticalEdges.push({
                  from: blocks[i],
                  to: successors[j]
                });
              }
            }
          }
        }
        var criticalEdgeCount = criticalEdges.length;
        if (criticalEdgeCount && debug) {
          writer.writeLn('Splitting: ' + criticalEdgeCount);
          this.trace(writer);
        }
        var edge;
        while (edge = criticalEdges.pop()) {
          var fromIndex = edge.from.successors.indexOf(edge.to);
          var toIndex = edge.to.predecessors.indexOf(edge.from);
          true;
          debug && writer.writeLn('Splitting critical edge: ' + edge.from + ' -> ' + edge.to);
          var toBlock = edge.to;
          var toRegion = toBlock.region;
          var control = toRegion.predecessors[toIndex];
          var region = new Region(control);
          var jump = new Jump(region);
          var block = this.buildBlock(region, jump);
          toRegion.predecessors[toIndex] = new Projection(jump, Projection.Type.TRUE);
          var fromBlock = edge.from;
          fromBlock.successors[fromIndex] = block;
          block.pushPredecessor(fromBlock);
          block.pushSuccessor(toBlock);
          toBlock.predecessors[toIndex] = block;
        }
        if (criticalEdgeCount && debug) {
          this.trace(writer);
        }
        if (criticalEdgeCount && !true) {
          true;
        }
        debug && writer.leave('<');
        return criticalEdgeCount;
      };
      constructor.prototype.allocateVariables = function allocateVariables() {
        var writer = debug && new IndentingWriter();
        debug && writer.enter('> Allocating Virtual Registers');
        var order = this.computeReversePostOrder();
        function allocate(node) {
          if (isProjection(node, Projection.Type.STORE)) {
            return;
          }
          if (node instanceof SetProperty) {
            return;
          }
          if (node instanceof Value) {
            node.variable = new Variable('v' + node.id);
            debug && writer.writeLn('Allocated: ' + node.variable + ' to ' + node);
          }
        }
        order.forEach(function (block) {
          block.nodes.forEach(allocate);
          if (block.phis) {
            block.phis.forEach(allocate);
          }
        });
        var blockMoves = [];
        for (var i = 0; i < order.length; i++) {
          var block = order[i];
          var phis = block.phis;
          var predecessors = block.predecessors;
          if (phis) {
            for (var j = 0; j < phis.length; j++) {
              var phi = phis[j];
              debug && writer.writeLn('Emitting moves for: ' + phi);
              var arguments = phi.args;
              true;
              for (var k = 0; k < predecessors.length; k++) {
                var predecessor = predecessors[k];
                var argument = arguments[k];
                if (argument.abstract || isProjection(argument, Projection.Type.STORE)) {
                  continue;
                }
                var moves = blockMoves[predecessor.id] || (blockMoves[predecessor.id] = []);
                argument = argument.variable || argument;
                if (phi.variable !== argument) {
                  moves.push(new Move(phi.variable, argument));
                }
              }
            }
          }
        }
        var blocks = this.blocks;
        blockMoves.forEach(function (moves, blockID) {
          var block = blocks[blockID];
          var temporary = 0;
          debug && writer.writeLn(block + ' Moves: ' + moves);
          while (moves.length) {
            for (var i = 0; i < moves.length; i++) {
              var move = moves[i];
              for (var j = 0; j < moves.length; j++) {
                if (i === j) {
                  continue;
                }
                if (moves[j].from === move.to) {
                  move = null;
                  break;
                }
              }
              if (move) {
                moves.splice(i--, 1);
                block.append(move);
              }
            }
            if (moves.length) {
              debug && writer.writeLn('Breaking Cycle');
              var move = moves[0];
              var temp = new Variable('t' + temporary++);
              blocks[blockID].append(new Move(temp, move.to));
              for (var i = 1; i < moves.length; i++) {
                if (moves[i].from === move.to) {
                  moves[i].from = temp;
                }
              }
            }
          }
        });
        debug && writer.leave('<');
      };
      constructor.prototype.scheduleEarly = function scheduleEarly() {
        var debugScheduler = false;
        var writer = debugScheduler && new IndentingWriter();
        debugScheduler && writer.enter('> Schedule Early');
        var cfg = this;
        var dfg = this.dfg;
        var scheduled = [];
        var roots = [];
        dfg.forEachInPreOrderDepthFirstSearch(function (node) {
          if (node instanceof Region || node instanceof Jump) {
            return;
          }
          if (node.control) {
            roots.push(node);
          }
          if (isPhi(node)) {
            node.args.forEach(function (input) {
              if (shouldFloat(input)) {
                input.mustNotFloat = true;
              }
            });
          }
        }, true);
        if (debugScheduler) {
          roots.forEach(function (node) {
            print('Root: ' + node);
          });
        }
        for (var i = 0; i < roots.length; i++) {
          var root = roots[i];
          if (root instanceof Phi) {
            var block = root.control.block;
            (block.phis || (block.phis = [])).push(root);
          }
          if (root.control) {
            schedule(root);
          }
        }
        function isScheduled(node) {
          return scheduled[node.id];
        }
        function shouldFloat(node) {
          if (node.mustNotFloat || node.shouldNotFloat) {
            return false;
          }
          if (node.mustFloat || node.shouldFloat) {
            return true;
          }
          if (node instanceof Parameter || node instanceof This || node instanceof Arguments) {
            return true;
          }
          return node instanceof Binary || node instanceof Unary || node instanceof Parameter;
        }
        function append(node) {
          true;
          scheduled[node.id] = true;
          true;
          if (shouldFloat(node)) {
          } else {
            node.control.block.append(node);
          }
        }
        function scheduleIn(node, region) {
          true;
          true;
          true;
          debugScheduler && writer.writeLn('Scheduled: ' + node + ' in ' + region);
          node.control = region;
          append(node);
        }
        function schedule(node) {
          debugScheduler && writer.enter('> Schedule: ' + node);
          var inputs = [];
          node.visitInputs(function (input) {
            if (isConstant(input)) {
              {
                return;
              }
            }
            if (isValue(input)) {
              inputs.push(followProjection(input));
            }
          });
          debugScheduler && writer.writeLn('Inputs: [' + inputs.map(toID) + '], length: ' + inputs.length);
          for (var i = 0; i < inputs.length; i++) {
            var input = inputs[i];
            if (isNotPhi(input) && !isScheduled(input)) {
              schedule(input);
            }
          }
          if (node.control) {
            if (node instanceof End || node instanceof Phi || node instanceof Start || isScheduled(node)) {
            } else {
              append(node);
            }
          } else {
            if (inputs.length) {
              var x = inputs[0].control;
              for (var i = 1; i < inputs.length; i++) {
                var y = inputs[i].control;
                if (x.block.dominatorDepth < y.block.dominatorDepth) {
                  x = y;
                }
              }
              scheduleIn(node, x);
            } else {
              scheduleIn(node, cfg.root.region);
            }
          }
          debugScheduler && writer.leave('<');
        }
        debugScheduler && writer.leave('<');
        roots.forEach(function (node) {
          node = followProjection(node);
          if (node === dfg.start || node instanceof Region) {
            return;
          }
          true;
        });
      };
      constructor.prototype.trace = function (writer) {
        var visited = [];
        var blocks = [];
        function next(block) {
          if (!visited[block.id]) {
            visited[block.id] = true;
            blocks.push(block);
            block.visitSuccessors(next);
          }
        }
        var root = this.root;
        var exit = this.exit;
        next(root);
        function colorOf(block) {
          return 'black';
        }
        function styleOf(block) {
          return 'filled';
        }
        function shapeOf(block) {
          true;
          if (block === root) {
            return 'house';
          } else if (block === exit) {
            return 'invhouse';
          }
          return 'box';
        }
        writer.writeLn('');
        writer.enter('digraph CFG {');
        writer.writeLn('graph [bgcolor = gray10];');
        writer.writeLn('edge [fontname = Consolas, fontsize = 11, color = white, fontcolor = white];');
        writer.writeLn('node [shape = box, fontname = Consolas, fontsize = 11, color = white, fontcolor = white, style = filled];');
        writer.writeLn('rankdir = TB;');
        blocks.forEach(function (block) {
          var loopInfo = '';
          var blockInfo = '';
          var intervalInfo = '';
          if (block.loops !== undefined) {
          }
          if (block.name !== undefined) {
            blockInfo += ' ' + block.name;
          }
          if (block.rpo !== undefined) {
            blockInfo += ' O: ' + block.rpo;
          }
          writer.writeLn('B' + block.id + ' [label = "B' + block.id + blockInfo + loopInfo + '", fillcolor = "' + colorOf(block) + '", shape=' + shapeOf(block) + ', style=' + styleOf(block) + '];');
        });
        blocks.forEach(function (block) {
          block.visitSuccessors(function (successor) {
            writer.writeLn('B' + block.id + ' -> ' + 'B' + successor.id);
          });
          if (block.dominator) {
            writer.writeLn('B' + block.id + ' -> ' + 'B' + block.dominator.id + ' [color = orange];');
          }
          if (block.follow) {
            writer.writeLn('B' + block.id + ' -> ' + 'B' + block.follow.id + ' [color = purple];');
          }
        });
        writer.leave('}');
        writer.writeLn('');
      };
      return constructor;
    }();
  var PeepholeOptimizer = function () {
      function constructor() {
      }
      function foldUnary(node, truthy) {
        true;
        if (isConstant(node.argument)) {
          return new Constant(node.operator.evaluate(node.argument.value));
        }
        if (truthy) {
          var argument = fold(node.argument, true);
          if (node.operator === Operator.TRUE) {
            return argument;
          }
          if (argument instanceof Unary) {
            if (node.operator === Operator.FALSE && argument.operator === Operator.FALSE) {
              return argument.argument;
            }
          } else {
            return new Unary(node.operator, argument);
          }
        }
        return node;
      }
      function foldBinary(node, truthy) {
        true;
        if (isConstant(node.left) && isConstant(node.right)) {
          return new Constant(node.operator.evaluate(node.left.value, node.right.value));
        }
        return node;
      }
      function fold(node, truthy) {
        if (node instanceof Unary) {
          return foldUnary(node, truthy);
        } else if (node instanceof Binary) {
          return foldBinary(node, truthy);
        }
        return node;
      }
      constructor.prototype.tryFold = fold;
      return constructor;
    }();
  exports.isConstant = isConstant;
  exports.Block = Block;
  exports.Node = Node;
  exports.Start = Start;
  exports.Null = Null;
  exports.Undefined = Undefined;
  exports.This = This;
  exports.Throw = Throw;
  exports.Arguments = Arguments;
  exports.ASGlobal = ASGlobal;
  exports.Projection = Projection;
  exports.Region = Region;
  exports.Latch = Latch;
  exports.Binary = Binary;
  exports.Unary = Unary;
  exports.Constant = Constant;
  exports.ASFindProperty = ASFindProperty;
  exports.GlobalProperty = GlobalProperty;
  exports.GetProperty = GetProperty;
  exports.SetProperty = SetProperty;
  exports.CallProperty = CallProperty;
  exports.ASCallProperty = ASCallProperty;
  exports.ASCallSuper = ASCallSuper;
  exports.ASGetProperty = ASGetProperty;
  exports.ASGetSuper = ASGetSuper;
  exports.ASHasProperty = ASHasProperty;
  exports.ASDeleteProperty = ASDeleteProperty;
  exports.ASGetDescendants = ASGetDescendants;
  exports.ASSetProperty = ASSetProperty;
  exports.ASSetSuper = ASSetSuper;
  exports.ASGetSlot = ASGetSlot;
  exports.ASSetSlot = ASSetSlot;
  exports.Call = Call;
  exports.ASNew = ASNew;
  exports.Phi = Phi;
  exports.Stop = Stop;
  exports.If = If;
  exports.Switch = Switch;
  exports.End = End;
  exports.Jump = Jump;
  exports.ASScope = ASScope;
  exports.Operator = Operator;
  exports.Variable = Variable;
  exports.Move = Move;
  exports.Copy = Copy;
  exports.Parameter = Parameter;
  exports.NewArray = NewArray;
  exports.NewObject = NewObject;
  exports.ASNewActivation = ASNewActivation;
  exports.KeyValuePair = KeyValuePair;
  exports.ASMultiname = ASMultiname;
  exports.DFG = DFG;
  exports.CFG = CFG;
  exports.Flags = Flags;
  exports.PeepholeOptimizer = PeepholeOptimizer;
}(typeof exports === 'undefined' ? IR = {} : exports));
var c4Options = systemOptions.register(new OptionSet('C4 Options'));
var enableC4 = c4Options.register(new Option('c4', 'c4', 'boolean', false, 'Enable the C4 compiler.'));
var c4TraceLevel = c4Options.register(new Option('tc4', 'tc4', 'number', 0, 'Compiler Trace Level'));
var enableRegisterAllocator = c4Options.register(new Option('ra', 'ra', 'boolean', false, 'Enable register allocator.'));
var getPublicQualifiedName = Multiname.getPublicQualifiedName;
var createName = function createName(namespaces, name) {
  if (isNumeric(name) || isObject(name)) {
    return name;
  }
  return new Multiname(namespaces, name);
};
(function (exports) {
  var Node = IR.Node;
  var Start = IR.Start;
  var Null = IR.Null;
  var Undefined = IR.Undefined;
  var This = IR.This;
  var Projection = IR.Projection;
  var Region = IR.Region;
  var Binary = IR.Binary;
  var Unary = IR.Unary;
  var Constant = IR.Constant;
  var Call = IR.Call;
  var Phi = IR.Phi;
  var Stop = IR.Stop;
  var Operator = IR.Operator;
  var Parameter = IR.Parameter;
  var NewArray = IR.NewArray;
  var NewObject = IR.NewObject;
  var KeyValuePair = IR.KeyValuePair;
  var isConstant = IR.isConstant;
  var DFG = IR.DFG;
  var CFG = IR.CFG;
  var writer = new IndentingWriter();
  var peepholeOptimizer = new IR.PeepholeOptimizer();
  var USE_TYPE_OF_DEFAULT_ARGUMENT_CHECKING = false;
  var State = function () {
      var nextID = 0;
      function constructor(index) {
        this.id = nextID += 1;
        this.index = index;
        this.local = [];
        this.stack = [];
        this.scope = [];
        this.store = Undefined;
        this.loads = [];
        this.saved = Undefined;
      }
      constructor.prototype.clone = function clone(index) {
        var s = new State();
        s.index = index !== undefined ? index : this.index;
        s.local = this.local.slice(0);
        s.stack = this.stack.slice(0);
        s.scope = this.scope.slice(0);
        s.loads = this.loads.slice(0);
        s.saved = this.saved;
        s.store = this.store;
        return s;
      };
      constructor.prototype.matches = function matches(other) {
        return this.stack.length === other.stack.length && this.scope.length === other.scope.length && this.local.length === other.local.length;
      };
      constructor.prototype.makeLoopPhis = function makeLoopPhis(control) {
        var s = new State();
        true;
        function makePhi(x) {
          var phi = new Phi(control, x);
          phi.isLoop = true;
          return phi;
        }
        s.index = this.index;
        s.local = this.local.map(makePhi);
        s.stack = this.stack.map(makePhi);
        s.scope = this.scope.map(makePhi);
        s.loads = this.loads.slice(0);
        s.saved = this.saved;
        s.store = makePhi(this.store);
        return s;
      };
      constructor.prototype.optimize = function optimize() {
        function optimize(x) {
          if (x instanceof Phi && !x.isLoop) {
            var args = x.args.unique();
            if (args.length === 1) {
              x.seal();
              Counter.count('Builder: OptimizedPhi');
              return args[0];
            }
          }
          return x;
        }
        this.local = this.local.map(optimize);
        this.stack = this.stack.map(optimize);
        this.scope = this.scope.map(optimize);
        this.saved = optimize(this.saved);
        this.store = optimize(this.store);
      };
      function mergeValue(control, a, b) {
        var phi = a instanceof Phi && a.control === control ? a : new Phi(control, a);
        phi.pushValue(b);
        return phi;
      }
      function mergeValues(control, a, b) {
        for (var i = 0; i < a.length; i++) {
          a[i] = mergeValue(control, a[i], b[i]);
        }
      }
      constructor.prototype.merge = function merge(control, other) {
        true;
        true;
        mergeValues(control, this.local, other.local);
        mergeValues(control, this.stack, other.stack);
        mergeValues(control, this.scope, other.scope);
        this.store = mergeValue(control, this.store, other.store);
        this.store.abstract = true;
      };
      constructor.prototype.trace = function trace(writer) {
        writer.writeLn(this.toString());
      };
      function toBriefString(x) {
        if (x instanceof Node) {
          return x.toString(true);
        }
        return x;
      }
      constructor.prototype.toString = function () {
        return '<' + String(this.id + ' @ ' + this.index).padRight(' ', 10) + (' M: ' + toBriefString(this.store)).padRight(' ', 14) + (' X: ' + toBriefString(this.saved)).padRight(' ', 14) + (' $: ' + this.scope.map(toBriefString).join(', ')).padRight(' ', 20) + (' L: ' + this.local.map(toBriefString).join(', ')).padRight(' ', 40) + (' S: ' + this.stack.map(toBriefString).join(', ')).padRight(' ', 60);
      };
      return constructor;
    }();
  function isNumericConstant(node) {
    return node instanceof Constant && isNumeric(node.value);
  }
  function isStringConstant(node) {
    return node instanceof Constant && isString(node.value);
  }
  function isMultinameConstant(node) {
    return node instanceof Constant && node.value instanceof Multiname;
  }
  function hasNumericType(node) {
    if (isNumericConstant(node)) {
      return true;
    }
    return node.ty && node.ty.isNumeric();
  }
  function typesAreEqual(a, b) {
    if (hasNumericType(a) && hasNumericType(b) || hasStringType(a) && hasStringType(b)) {
      return true;
    }
    return false;
  }
  function hasStringType(node) {
    if (isStringConstant(node)) {
      return true;
    }
    return node.ty && node.ty.isString();
  }
  function constant(value) {
    return new Constant(value);
  }
  function qualifiedNameConstant(name) {
    return constant(Multiname.getQualifiedName(name));
  }
  function getJSPropertyWithState(state, object, path) {
    true;
    var names = path.split('.');
    var node = object;
    for (var i = 0; i < names.length; i++) {
      node = new IR.GetProperty(null, state.store, node, constant(names[i]));
      node.shouldFloat = true;
      state.loads.push(node);
    }
    return node;
  }
  function globalProperty(name) {
    var node = new IR.GlobalProperty(name);
    node.mustFloat = true;
    return node;
  }
  function warn(message) {
  }
  function unary(operator, argument) {
    var node = new Unary(operator, argument);
    if (peepholeOptimizer) {
      node = peepholeOptimizer.tryFold(node);
    }
    return node;
  }
  function binary(operator, left, right) {
    var node = new Binary(operator, left, right);
    if (left.ty && left.ty !== Type.Any && left.ty === right.ty) {
      if (operator === Operator.EQ) {
        node.operator = Operator.SEQ;
      } else if (operator === Operator.NE) {
        node.operator = Operator.SNE;
      }
    }
    if (peepholeOptimizer) {
      node = peepholeOptimizer.tryFold(node);
    }
    return node;
  }
  function coerceInt(value) {
    return binary(Operator.OR, value, constant(0));
  }
  function coerceUint(value) {
    return binary(Operator.URSH, value, constant(0));
  }
  function coerceNumber(value) {
    if (hasNumericType(value)) {
      return value;
    }
    return unary(Operator.PLUS, value);
  }
  function coerceBoolean(value) {
    return unary(Operator.FALSE, unary(Operator.FALSE, value));
  }
  function shouldNotFloat(node) {
    node.shouldNotFloat = true;
    return node;
  }
  function shouldFloat(node) {
    true;
    node.shouldFloat = true;
    return node;
  }
  function mustFloat(node) {
    node.mustFloat = true;
    return node;
  }
  function callPure(callee, object, args) {
    return new Call(null, null, callee, object, args, IR.Flags.PRISTINE);
  }
  function callGlobalProperty(name, value) {
    return callPure(globalProperty(name), null, [
      value
    ]);
  }
  function convertString(value) {
    if (isStringConstant(value)) {
      return value;
    }
    return callPure(globalProperty('String'), null, [
      value
    ]);
  }
  function coerceString(value) {
    if (isStringConstant(value)) {
      return value;
    }
    return callPure(globalProperty('asCoerceString'), null, [
      value
    ]);
  }
  var coerceObject = callGlobalProperty.bind(null, 'asCoerceObject');
  var coercers = createEmptyObject();
  coercers[Multiname.Int] = coerceInt;
  coercers[Multiname.Uint] = coerceUint;
  coercers[Multiname.Number] = coerceNumber;
  coercers[Multiname.String] = coerceString;
  coercers[Multiname.Object] = coerceObject;
  coercers[Multiname.Boolean] = coerceBoolean;
  function getCoercerForType(multiname) {
    true;
    return coercers[Multiname.getQualifiedName(multiname)];
  }
  var callableConstructors = createEmptyObject();
  callableConstructors[Multiname.Int] = coerceInt;
  callableConstructors[Multiname.Uint] = coerceUint;
  callableConstructors[Multiname.Number] = callGlobalProperty.bind(null, 'Number');
  callableConstructors[Multiname.String] = callGlobalProperty.bind(null, 'String');
  callableConstructors[Multiname.Object] = callGlobalProperty.bind(null, 'Object');
  callableConstructors[Multiname.Boolean] = callGlobalProperty.bind(null, 'Boolean');
  function getCallableConstructorForType(multiname) {
    true;
    return callableConstructors[Multiname.getQualifiedName(multiname)];
  }
  var Builder = function () {
      function builder(methodInfo, scope, hasDynamicScope) {
        true;
        this.abc = methodInfo.abc;
        this.scope = scope;
        this.methodInfo = methodInfo;
        this.hasDynamicScope = hasDynamicScope;
      }
      builder.prototype.buildStart = function (start) {
        var mi = this.methodInfo;
        var state = start.entryState = new State(0);
        state.local.push(new This(start));
        var parameterIndexOffset = this.hasDynamicScope ? 1 : 0;
        var parameterCount = mi.parameters.length;
        for (var i = 0; i < parameterCount; i++) {
          state.local.push(new Parameter(start, parameterIndexOffset + i, mi.parameters[i].name));
        }
        for (var i = parameterCount; i < mi.localCount; i++) {
          state.local.push(Undefined);
        }
        state.store = new Projection(start, Projection.Type.STORE);
        if (this.hasDynamicScope) {
          start.scope = new Parameter(start, 0, SAVED_SCOPE_NAME);
        } else {
          start.scope = new Constant(this.scope);
        }
        state.saved = new Projection(start, Projection.Type.SCOPE);
        start.domain = new Constant(this.domain);
        var args = new IR.Arguments(start);
        if (mi.needsRest() || mi.needsArguments()) {
          var offset = constant(parameterIndexOffset + (mi.needsRest() ? parameterCount : 0));
          state.local[parameterCount + 1] = new Call(start, state.store, globalProperty('sliceArguments'), null, [
            args,
            offset
          ], IR.Flags.PRISTINE);
        }
        var argumentsLength = getJSPropertyWithState(state, args, 'length');
        for (var i = 0; i < parameterCount; i++) {
          var parameter = mi.parameters[i];
          var index = i + 1;
          var local = state.local[index];
          if (parameter.value !== undefined) {
            var condition;
            if (USE_TYPE_OF_DEFAULT_ARGUMENT_CHECKING) {
              condition = new IR.Binary(Operator.SEQ, new IR.Unary(Operator.TYPE_OF, local), constant('undefined'));
            } else {
              condition = new IR.Binary(Operator.LT, argumentsLength, constant(parameterIndexOffset + i + 1));
            }
            local = new IR.Latch(null, condition, constant(parameter.value), local);
          }
          if (parameter.type && !parameter.type.isAnyName()) {
            var coercer = getCoercerForType(parameter.type);
            if (coercer) {
              local = coercer(local);
            } else if (c4CoerceNonPrimitiveParameters) {
              local = new Call(start, state.store, globalProperty('asCoerceByMultiname'), null, [
                constant(this.abc.applicationDomain),
                constant(parameter.type),
                local
              ], true);
            }
          }
          state.local[index] = local;
        }
        return start;
      };
      builder.prototype.buildGraph = function buildGraph(callerRegion, callerState, inlineArguments) {
        var analysis = this.methodInfo.analysis;
        var blocks = analysis.blocks;
        var bytecodes = analysis.bytecodes;
        var methodInfo = this.methodInfo;
        var ints = this.abc.constantPool.ints;
        var uints = this.abc.constantPool.uints;
        var doubles = this.abc.constantPool.doubles;
        var strings = this.abc.constantPool.strings;
        var methods = this.abc.methods;
        var classes = this.abc.classes;
        var multinames = this.abc.constantPool.multinames;
        var domain = new Constant(this.abc.applicationDomain);
        var traceBuilder = c4TraceLevel.value > 2;
        var stopPoints = [];
        for (var i = 0; i < blocks.length; i++) {
          blocks[i].blockDominatorOrder = i;
        }
        var worklist = new Shumway.SortedList(function compare(a, b) {
            return a.block.blockDominatorOrder - b.block.blockDominatorOrder;
          });
        var start = new Start(null);
        this.buildStart(start);
        var createFunctionCallee = globalProperty('createFunction');
        worklist.push({
          region: start,
          block: blocks[0]
        });
        var next;
        while (next = worklist.pop()) {
          buildBlock(next.region, next.block, next.region.entryState.clone()).forEach(function (stop) {
            var target = stop.target;
            var region = target.region;
            if (region) {
              traceBuilder && writer.enter('Merging into region: ' + region + ' @ ' + target.position + ', block ' + target.bid + ' {');
              traceBuilder && writer.writeLn('  R ' + region.entryState);
              traceBuilder && writer.writeLn('+ I ' + stop.state);
              region.entryState.merge(region, stop.state);
              region.predecessors.push(stop.control);
              traceBuilder && writer.writeLn('  = ' + region.entryState);
              traceBuilder && writer.leave('}');
            } else {
              region = target.region = new Region(stop.control);
              if (target.loop) {
                traceBuilder && writer.writeLn('Adding PHIs to loop region.');
              }
              region.entryState = target.loop ? stop.state.makeLoopPhis(region) : stop.state.clone(target.position);
              traceBuilder && writer.writeLn('Adding new region: ' + region + ' @ ' + target.position + ' to worklist.');
              worklist.push({
                region: region,
                block: target
              });
            }
          });
          traceBuilder && writer.enter('Worklist: {');
          worklist.forEach(function (item) {
            traceBuilder && writer.writeLn(item.region + ' ' + item.block.bdo + ' ' + item.region.entryState);
          });
          traceBuilder && writer.leave('}');
        }
        traceBuilder && writer.writeLn('Done');
        function buildBlock(region, block, state) {
          true;
          state.optimize();
          var typeState = block.entryState;
          if (typeState) {
            traceBuilder && writer.writeLn('Type State: ' + typeState);
            for (var i = 0; i < typeState.local.length; i++) {
              var type = typeState.local[i];
              var local = state.local[i];
              if (local.ty) {
              } else {
                local.ty = type;
              }
            }
          }
          var local = state.local;
          var stack = state.stack;
          var scope = state.scope;
          function savedScope() {
            return state.saved;
          }
          function topScope(depth) {
            if (depth !== undefined) {
              if (depth < scope.length) {
                return scope[scope.length - 1 - depth];
              } else if (depth === scope.length) {
                return savedScope();
              } else {
                var s = savedScope();
                var savedScopeDepth = depth - scope.length;
                for (var i = 0; i < savedScopeDepth; i++) {
                  s = getJSProperty(s, 'parent');
                }
                return s;
              }
            }
            if (scope.length > 0) {
              return scope.top();
            }
            return savedScope();
          }
          var object, receiver, index, callee, value, multiname, type, args, pristine, left, right, operator;
          function push(x) {
            true;
            if (bc.ti) {
              if (x.ty) {
              } else {
                x.ty = bc.ti.type;
              }
            }
            stack.push(x);
          }
          function pop() {
            return stack.pop();
          }
          function popMany(count) {
            return stack.popMany(count);
          }
          function pushLocal(index) {
            push(local[index]);
          }
          function popLocal(index) {
            local[index] = shouldNotFloat(pop());
          }
          function buildMultiname(index) {
            var multiname = multinames[index];
            var namespaces, name, flags = multiname.flags;
            if (multiname.isRuntimeName()) {
              name = stack.pop();
            } else {
              name = constant(multiname.name);
            }
            if (multiname.isRuntimeNamespace()) {
              namespaces = shouldFloat(new NewArray(region, [
                pop()
              ]));
            } else {
              namespaces = constant(multiname.namespaces);
            }
            return new IR.ASMultiname(namespaces, name, flags);
          }
          function simplifyName(name) {
            if (isMultinameConstant(name) && Multiname.isQName(name.value)) {
              return constant(Multiname.getQualifiedName(name.value));
            }
            return name;
          }
          function getGlobalScope(ti) {
            if (ti && ti.object) {
              return constant(ti.object);
            }
            return new IR.ASGlobal(null, savedScope());
          }
          function findProperty(multiname, strict, ti) {
            var slowPath = new IR.ASFindProperty(region, state.store, topScope(), multiname, domain, strict);
            if (ti) {
              if (ti.object) {
                if (ti.object instanceof Global && !ti.object.isExecuting()) {
                  warn('Can\'t optimize findProperty ' + multiname + ', global object is not yet executed or executing.');
                  return slowPath;
                }
                return constant(ti.object);
              } else if (ti.scopeDepth !== undefined) {
                return getScopeObject(topScope(ti.scopeDepth));
              }
            }
            warn('Can\'t optimize findProperty ' + multiname);
            return slowPath;
          }
          function getJSProperty(object, path) {
            return getJSPropertyWithState(state, object, path);
          }
          function coerce(multiname, value) {
            if (false && isConstant(value)) {
              return constant(asCoerceByMultiname(domain.value, multiname, value.value));
            } else {
              var coercer = getCoercerForType(multiname);
              if (coercer) {
                return coercer(value);
              }
            }
            if (c4CoerceNonPrimitive) {
              return call(globalProperty('asCoerceByMultiname'), null, [
                domain,
                constant(multiname),
                value
              ]);
            }
            return value;
          }
          function getScopeObject(scope) {
            if (scope instanceof IR.ASScope) {
              return scope.object;
            }
            return getJSProperty(scope, 'object');
          }
          function store(node) {
            state.store = new Projection(node, Projection.Type.STORE);
            node.loads = state.loads.slice(0);
            state.loads.length = 0;
            return node;
          }
          function load(node) {
            state.loads.push(node);
            return node;
          }
          function resolveMultinameGlobally(multiname) {
            var namespaces = multiname.namespaces;
            var name = multiname.name;
            if (!Shumway.AVM2.Runtime.globalMultinameAnalysis.value) {
              return;
            }
            if (!isConstant(namespaces) || !isConstant(name) || multiname.isAttribute()) {
              Counter.count('GlobalMultinameResolver: Cannot resolve runtime multiname or attribute.');
              return;
            }
            if (isNumeric(name.value) || !isString(name.value) || !name.value) {
              Counter.count('GlobalMultinameResolver: Cannot resolve numeric or any names.');
              return false;
            }
            return GlobalMultinameResolver.resolveMultiname(new Multiname(namespaces.value, name.value, multiname.flags));
          }
          function callSuper(scope, object, multiname, args, ti) {
            if (ti && ti.trait && ti.trait.isMethod() && ti.baseClass) {
              var qn = VM_OPEN_METHOD_PREFIX + Multiname.getQualifiedName(ti.trait.name);
              var callee = getJSProperty(constant(ti.baseClass), 'traitsPrototype.' + qn);
              return call(callee, object, args);
            }
            return store(new IR.ASCallSuper(region, state.store, object, multiname, args, IR.Flags.PRISTINE, scope));
          }
          function getSuper(scope, object, multiname, ti) {
            if (ti && ti.trait && ti.trait.isGetter() && ti.baseClass) {
              var qn = VM_OPEN_GET_METHOD_PREFIX + Multiname.getQualifiedName(ti.trait.name);
              var callee = getJSProperty(constant(ti.baseClass), 'traitsPrototype.' + qn);
              return call(callee, object, []);
            }
            return store(new IR.ASGetSuper(region, state.store, object, multiname, scope));
          }
          function setSuper(scope, object, multiname, value, ti) {
            if (ti && ti.trait && ti.trait.isSetter() && ti.baseClass) {
              var qn = VM_OPEN_SET_METHOD_PREFIX + Multiname.getQualifiedName(ti.trait.name);
              var callee = getJSProperty(constant(ti.baseClass), 'traitsPrototype.' + qn);
              return call(callee, object, [
                value
              ]);
            }
            return store(new IR.ASSetSuper(region, state.store, object, multiname, value, scope));
          }
          function constructSuper(scope, object, args, ti) {
            if (ti) {
              if (ti.noCallSuperNeeded) {
                return;
              } else if (ti.baseClass) {
                var callee = getJSProperty(constant(ti.baseClass), 'instanceConstructorNoInitialize');
                call(callee, object, args);
                return;
              }
            }
            callee = getJSProperty(scope, 'object.baseClass.instanceConstructorNoInitialize');
            call(callee, object, args);
            return;
          }
          function callProperty(object, multiname, args, isLex, ti) {
            if (ti && ti.trait) {
              if (ti.trait.isMethod()) {
                var openQn;
                if (ti.trait.holder instanceof InstanceInfo && ti.trait.holder.isInterface()) {
                  openQn = Multiname.getPublicQualifiedName(Multiname.getName(ti.trait.name));
                } else {
                  openQn = Multiname.getQualifiedName(ti.trait.name);
                }
                openQn = VM_OPEN_METHOD_PREFIX + openQn;
                return store(new IR.CallProperty(region, state.store, object, constant(openQn), args, IR.Flags.PRISTINE));
              } else if (ti.trait.isClass()) {
                var constructor = getCallableConstructorForType(ti.trait.name);
                if (constructor) {
                  return constructor(args[0]);
                }
                var qn = Multiname.getQualifiedName(ti.trait.name);
                return store(new IR.CallProperty(region, state.store, object, constant(qn), args, 0));
              }
            } else if (ti && ti.propertyQName) {
              return store(new IR.CallProperty(region, state.store, object, constant(ti.propertyQName), args, IR.Flags.PRISTINE));
            }
            var qn = resolveMultinameGlobally(multiname);
            if (qn) {
              return store(new IR.ASCallProperty(region, state.store, object, constant(Multiname.getQualifiedName(qn)), args, IR.Flags.PRISTINE | IR.Flags.RESOLVED, isLex));
            }
            return store(new IR.ASCallProperty(region, state.store, object, multiname, args, IR.Flags.PRISTINE, isLex));
          }
          function getProperty(object, multiname, ti, getOpenMethod) {
            true;
            getOpenMethod = !(!getOpenMethod);
            if (ti) {
              if (ti.trait) {
                if (ti.trait.isConst() && ti.trait.hasDefaultValue) {
                  return constant(ti.trait.value);
                }
                var get = new IR.GetProperty(region, state.store, object, qualifiedNameConstant(ti.trait.name));
                return ti.trait.isGetter() ? store(get) : load(get);
              }
              if (ti.propertyQName) {
                return store(new IR.GetProperty(region, state.store, object, constant(ti.propertyQName)));
              } else if (ti.isDirectlyReadable) {
                return store(new IR.GetProperty(region, state.store, object, multiname.name));
              } else if (ti.isIndexedReadable) {
                return store(new IR.ASGetProperty(region, state.store, object, multiname, IR.Flags.INDEXED | (getOpenMethod ? IR.Flagas.IS_METHOD : 0)));
              }
            }
            warn('Can\'t optimize getProperty ' + multiname);
            var qn = resolveMultinameGlobally(multiname);
            if (qn) {
              return store(new IR.ASGetProperty(region, state.store, object, constant(Multiname.getQualifiedName(qn)), IR.Flags.RESOLVED | (getOpenMethod ? IR.Flagas.IS_METHOD : 0)));
            }
            Counter.count('Compiler: Slow ASGetProperty');
            return store(new IR.ASGetProperty(region, state.store, object, multiname, getOpenMethod ? IR.Flagas.IS_METHOD : 0));
          }
          function setProperty(object, multiname, value, ti) {
            true;
            if (ti) {
              if (ti.trait) {
                var coercer = ti.trait.typeName ? getCoercerForType(ti.trait.typeName) : null;
                if (coercer) {
                  value = coercer(value);
                }
                store(new IR.SetProperty(region, state.store, object, qualifiedNameConstant(ti.trait.name), value));
                return;
              }
              if (ti.propertyQName) {
                return store(new IR.SetProperty(region, state.store, object, constant(ti.propertyQName), value));
              } else if (ti.isDirectlyWriteable) {
                return store(new IR.SetProperty(region, state.store, object, multiname.name, value));
              } else if (ti.isIndexedWriteable) {
                return store(new IR.ASSetProperty(region, state.store, object, multiname, value, IR.Flags.INDEXED));
              }
            }
            warn('Can\'t optimize setProperty ' + multiname);
            var qn = resolveMultinameGlobally(multiname);
            if (qn) {
            }
            return store(new IR.ASSetProperty(region, state.store, object, multiname, value, 0));
          }
          function getDescendants(object, name, ti) {
            name = simplifyName(name);
            return new IR.ASGetDescendants(region, state.store, object, name);
          }
          function getSlot(object, index, ti) {
            if (ti) {
              var trait = ti.trait;
              if (trait) {
                if (trait.isConst() && ti.trait.hasDefaultValue) {
                  return constant(trait.value);
                }
                var slotQn = Multiname.getQualifiedName(trait.name);
                return store(new IR.GetProperty(region, state.store, object, constant(slotQn)));
              }
            }
            warn('Can\'t optimize getSlot ' + index);
            return store(new IR.ASGetSlot(null, state.store, object, index));
          }
          function setSlot(object, index, value, ti) {
            if (ti) {
              var trait = ti.trait;
              if (trait) {
                var slotQn = Multiname.getQualifiedName(trait.name);
                store(new IR.SetProperty(region, state.store, object, constant(slotQn), value));
                return;
              }
            }
            warn('Can\'t optimize setSlot ' + index);
            store(new IR.ASSetSlot(region, state.store, object, index, value));
          }
          function call(callee, object, args) {
            return store(new Call(region, state.store, callee, object, args, IR.Flags.PRISTINE));
          }
          function callCall(callee, object, args, pristine) {
            return store(new Call(region, state.store, callee, object, args, pristine ? IR.Flags.PRISTINE : 0));
          }
          function truthyCondition(operator) {
            var right;
            if (operator.isBinary()) {
              right = pop();
            }
            var left = pop();
            var node;
            if (right) {
              node = binary(operator, left, right);
            } else {
              node = unary(operator, left);
            }
            if (peepholeOptimizer) {
              node = peepholeOptimizer.tryFold(node, true);
            }
            return node;
          }
          function negatedTruthyCondition(operator) {
            var node = unary(Operator.FALSE, truthyCondition(operator));
            if (peepholeOptimizer) {
              node = peepholeOptimizer.tryFold(node, true);
            }
            return node;
          }
          function pushExpression(operator, toInt) {
            var left, right;
            if (operator.isBinary()) {
              right = pop();
              left = pop();
              if (toInt) {
                right = coerceInt(right);
                left = coerceInt(left);
              }
              push(binary(operator, left, right));
            } else {
              left = pop();
              if (toInt) {
                left = coerceInt(left);
              }
              push(unary(operator, left));
            }
          }
          var stops = null;
          function buildIfStops(predicate) {
            true;
            var _if = new IR.If(region, predicate);
            stops = [
              {
                control: new Projection(_if, Projection.Type.FALSE),
                target: bytecodes[bc.position + 1],
                state: state
              },
              {
                control: new Projection(_if, Projection.Type.TRUE),
                target: bc.target,
                state: state
              }
            ];
          }
          function buildJumpStop() {
            true;
            stops = [
              {
                control: region,
                target: bc.target,
                state: state
              }
            ];
          }
          function buildThrowStop() {
            true;
            stops = [];
          }
          function buildReturnStop() {
            true;
            stops = [];
          }
          function buildSwitchStops(determinant) {
            true;
            if (bc.targets.length > 2) {
              stops = [];
              var _switch = new IR.Switch(region, determinant);
              for (var i = 0; i < bc.targets.length; i++) {
                stops.push({
                  control: new Projection(_switch, Projection.Type.CASE, constant(i)),
                  target: bc.targets[i],
                  state: state
                });
              }
            } else {
              true;
              var predicate = binary(Operator.SEQ, determinant, constant(0));
              var _if = new IR.If(region, predicate);
              stops = [
                {
                  control: new Projection(_if, Projection.Type.FALSE),
                  target: bc.targets[1],
                  state: state
                },
                {
                  control: new Projection(_if, Projection.Type.TRUE),
                  target: bc.targets[0],
                  state: state
                }
              ];
            }
          }
          if (traceBuilder) {
            writer.writeLn('Processing Region: ' + region + ', Block: ' + block.bid);
            writer.enter(('> state: ' + region.entryState.toString()).padRight(' ', 100));
          }
          region.processed = true;
          var bc;
          for (var bci = block.position, end = block.end.position; bci <= end; bci++) {
            bc = bytecodes[bci];
            var op = bc.op;
            state.index = bci;
            switch (op) {
            case 3:
              store(new IR.Throw(region, pop()));
              stopPoints.push({
                region: region,
                store: state.store,
                value: Undefined
              });
              buildThrowStop();
              break;
            case 98:
              pushLocal(bc.index);
              break;
            case 208:
            case 209:
            case 210:
            case 211:
              pushLocal(op - OP_getlocal0);
              break;
            case 99:
              popLocal(bc.index);
              break;
            case 212:
            case 213:
            case 214:
            case 215:
              popLocal(op - OP_setlocal0);
              break;
            case 28:
              scope.push(new IR.ASScope(topScope(), pop(), true));
              break;
            case 48:
              scope.push(new IR.ASScope(topScope(), pop(), false));
              break;
            case 29:
              scope.pop();
              break;
            case 100:
              push(getGlobalScope(bc.ti));
              break;
            case 101:
              push(getScopeObject(state.scope[bc.index]));
              break;
            case 93:
              push(findProperty(buildMultiname(bc.index), true, bc.ti));
              break;
            case 94:
              push(findProperty(buildMultiname(bc.index), false, bc.ti));
              break;
            case 102:
              multiname = buildMultiname(bc.index);
              object = pop();
              push(getProperty(object, multiname, bc.ti, false));
              break;
            case 89:
              multiname = buildMultiname(bc.index);
              object = pop();
              push(getDescendants(object, multiname, bc.ti));
              break;
            case 96:
              multiname = buildMultiname(bc.index);
              push(getProperty(findProperty(multiname, true, bc.ti), multiname, bc.ti, false));
              break;
            case 104:
            case 97:
              value = pop();
              multiname = buildMultiname(bc.index);
              object = pop();
              setProperty(object, multiname, value, bc.ti);
              break;
            case 106:
              multiname = buildMultiname(bc.index);
              object = pop();
              push(store(new IR.ASDeleteProperty(region, state.store, object, multiname)));
              break;
            case 108:
              object = pop();
              push(getSlot(object, constant(bc.index), bc.ti));
              break;
            case 109:
              value = pop();
              object = pop();
              setSlot(object, constant(bc.index), value, bc.ti);
              break;
            case 4:
              multiname = buildMultiname(bc.index);
              object = pop();
              push(getSuper(savedScope(), object, multiname, bc.ti));
              break;
            case 5:
              value = pop();
              multiname = buildMultiname(bc.index);
              object = pop();
              setSuper(savedScope(), object, multiname, value, bc.ti);
              break;
            case 241:
            case 240:
              break;
            case 64:
              push(callPure(createFunctionCallee, null, [
                constant(methods[bc.index]),
                topScope(),
                constant(true)
              ]));
              break;
            case 65:
              args = popMany(bc.argCount);
              object = pop();
              callee = pop();
              push(callCall(callee, object, args));
              break;
            case 70:
            case 79:
            case 76:
              args = popMany(bc.argCount);
              multiname = buildMultiname(bc.index);
              object = pop();
              value = callProperty(object, multiname, args, op === OP_callproplex, bc.ti);
              if (op !== OP_callpropvoid) {
                push(value);
              }
              break;
            case 69:
            case 78:
              multiname = buildMultiname(bc.index);
              args = popMany(bc.argCount);
              object = pop();
              value = callSuper(savedScope(), object, multiname, args, bc.ti);
              if (op !== OP_callsupervoid) {
                push(value);
              }
              break;
            case 66:
              args = popMany(bc.argCount);
              object = pop();
              push(store(new IR.ASNew(region, state.store, object, args)));
              break;
            case 73:
              args = popMany(bc.argCount);
              object = pop();
              constructSuper(savedScope(), object, args, bc.ti);
              break;
            case 74:
              args = popMany(bc.argCount);
              multiname = buildMultiname(bc.index);
              object = pop();
              callee = getProperty(object, multiname, bc.ti, false);
              push(store(new IR.ASNew(region, state.store, callee, args)));
              break;
            case 128:
              if (bc.ti && bc.ti.noCoercionNeeded) {
                Counter.count('Compiler: NoCoercionNeeded');
                break;
              } else {
                Counter.count('Compiler: CoercionNeeded');
              }
              value = pop();
              push(coerce(multinames[bc.index], value));
              break;
            case 131:
            case 115:
              push(coerceInt(pop()));
              break;
            case 136:
            case 116:
              push(coerceUint(pop()));
              break;
            case 132:
            case 117:
              push(coerceNumber(pop()));
              break;
            case 129:
            case 118:
              push(coerceBoolean(pop()));
              break;
            case 120:
              push(call(globalProperty('checkFilter'), null, [
                pop()
              ]));
              break;
            case 130:
              break;
            case 133:
              push(coerceString(pop()));
              break;
            case 112:
              push(convertString(pop()));
              break;
            case 135:
              type = pop();
              if (c4AsTypeLate) {
                value = pop();
                push(call(globalProperty('asAsType'), null, [
                  type,
                  value
                ]));
              }
              break;
            case 72:
            case 71:
              value = Undefined;
              if (op === OP_returnvalue) {
                value = pop();
                if (methodInfo.returnType) {
                  if (!(bc.ti && bc.ti.noCoercionNeeded)) {
                    value = coerce(methodInfo.returnType, value);
                  }
                }
              }
              stopPoints.push({
                region: region,
                store: state.store,
                value: value
              });
              buildReturnStop();
              break;
            case 30:
            case 35:
              index = pop();
              object = pop();
              push(new IR.CallProperty(region, state.store, object, constant(op === OP_nextname ? 'asNextName' : 'asNextValue'), [
                index
              ], IR.Flags.PRISTINE));
              break;
            case 50:
              var temp = call(globalProperty('asHasNext2'), null, [
                  local[bc.object],
                  local[bc.index]
                ]);
              local[bc.object] = getJSProperty(temp, 'object');
              push(local[bc.index] = getJSProperty(temp, 'index'));
              break;
            case 32:
              push(Null);
              break;
            case 33:
              push(Undefined);
              break;
            case 34:
              notImplemented();
              break;
            case 36:
              push(constant(bc.value));
              break;
            case 37:
              push(constant(bc.value));
              break;
            case 44:
              push(constant(strings[bc.index]));
              break;
            case 45:
              push(constant(ints[bc.index]));
              break;
            case 46:
              push(constant(uints[bc.index]));
              break;
            case 47:
              push(constant(doubles[bc.index]));
              break;
            case 38:
              push(constant(true));
              break;
            case 39:
              push(constant(false));
              break;
            case 40:
              push(constant(NaN));
              break;
            case 41:
              pop();
              break;
            case 42:
              value = shouldNotFloat(pop());
              push(value);
              push(value);
              break;
            case 43:
              state.stack.push(pop(), pop());
              break;
            case 239:
            case OP_debugline:
            case OP_debugfile:
              break;
            case 12:
              buildIfStops(negatedTruthyCondition(Operator.LT));
              break;
            case 24:
              buildIfStops(truthyCondition(Operator.GE));
              break;
            case 13:
              buildIfStops(negatedTruthyCondition(Operator.LE));
              break;
            case 23:
              buildIfStops(truthyCondition(Operator.GT));
              break;
            case 14:
              buildIfStops(negatedTruthyCondition(Operator.GT));
              break;
            case 22:
              buildIfStops(truthyCondition(Operator.LE));
              break;
            case 15:
              buildIfStops(negatedTruthyCondition(Operator.GE));
              break;
            case 21:
              buildIfStops(truthyCondition(Operator.LT));
              break;
            case 16:
              buildJumpStop();
              break;
            case 17:
              buildIfStops(truthyCondition(Operator.TRUE));
              break;
            case 18:
              buildIfStops(truthyCondition(Operator.FALSE));
              break;
            case 19:
              buildIfStops(truthyCondition(Operator.EQ));
              break;
            case 20:
              buildIfStops(truthyCondition(Operator.NE));
              break;
            case 25:
              buildIfStops(truthyCondition(Operator.SEQ));
              break;
            case 26:
              buildIfStops(truthyCondition(Operator.SNE));
              break;
            case 27:
              buildSwitchStops(pop());
              break;
            case 150:
              pushExpression(Operator.FALSE);
              break;
            case 151:
              pushExpression(Operator.BITWISE_NOT);
              break;
            case 160:
              right = pop();
              left = pop();
              if (typesAreEqual(left, right)) {
                operator = Operator.ADD;
              } else if (Shumway.AVM2.Runtime.useAsAdd) {
                operator = Operator.AS_ADD;
              } else {
                operator = Operator.ADD;
              }
              push(binary(operator, left, right));
              break;
            case 197:
              pushExpression(Operator.ADD, true);
              break;
            case 161:
              pushExpression(Operator.SUB);
              break;
            case 198:
              pushExpression(Operator.SUB, true);
              break;
            case 162:
              pushExpression(Operator.MUL);
              break;
            case 199:
              pushExpression(Operator.MUL, true);
              break;
            case 163:
              pushExpression(Operator.DIV);
              break;
            case 164:
              pushExpression(Operator.MOD);
              break;
            case 165:
              pushExpression(Operator.LSH);
              break;
            case 166:
              pushExpression(Operator.RSH);
              break;
            case 167:
              pushExpression(Operator.URSH);
              break;
            case 168:
              pushExpression(Operator.AND);
              break;
            case 169:
              pushExpression(Operator.OR);
              break;
            case 170:
              pushExpression(Operator.XOR);
              break;
            case 171:
              pushExpression(Operator.EQ);
              break;
            case 172:
              pushExpression(Operator.SEQ);
              break;
            case 173:
              pushExpression(Operator.LT);
              break;
            case 174:
              pushExpression(Operator.LE);
              break;
            case 175:
              pushExpression(Operator.GT);
              break;
            case 176:
              pushExpression(Operator.GE);
              break;
            case 144:
              pushExpression(Operator.NEG);
              break;
            case 196:
              pushExpression(Operator.NEG, true);
              break;
            case 145:
            case 192:
            case 147:
            case 193:
              push(constant(1));
              if (op === OP_increment || op === OP_decrement) {
                push(coerceNumber(pop()));
              } else {
                push(coerceInt(pop()));
              }
              if (op === OP_increment || op === OP_increment_i) {
                pushExpression(Operator.ADD);
              } else {
                pushExpression(Operator.SUB);
              }
              break;
            case 146:
            case 194:
            case 148:
            case 195:
              push(constant(1));
              if (op === OP_inclocal || op === OP_declocal) {
                push(coerceNumber(local[bc.index]));
              } else {
                push(coerceInt(local[bc.index]));
              }
              if (op === OP_inclocal || op === OP_inclocal_i) {
                pushExpression(Operator.ADD);
              } else {
                pushExpression(Operator.SUB);
              }
              popLocal(bc.index);
              break;
            case 177:
              type = pop();
              value = pop();
              push(call(getJSProperty(type, 'isInstanceOf'), null, [
                value
              ]));
              break;
            case 178:
              value = pop();
              multiname = buildMultiname(bc.index);
              type = getProperty(findProperty(multiname, false), multiname);
              push(call(globalProperty('asIsType'), null, [
                type,
                value
              ]));
              break;
            case 179:
              type = pop();
              value = pop();
              push(call(globalProperty('asIsType'), null, [
                type,
                value
              ]));
              break;
            case 180:
              object = pop();
              value = pop();
              multiname = new IR.ASMultiname(Undefined, value, 0);
              push(store(new IR.ASHasProperty(region, state.store, object, multiname)));
              break;
            case 149:
              push(call(globalProperty('asTypeOf'), null, [
                pop()
              ]));
              break;
            case 8:
              push(Undefined);
              popLocal(bc.index);
              break;
            case 83:
              args = popMany(bc.argCount);
              type = pop();
              callee = globalProperty('applyType');
              push(call(callee, null, [
                domain,
                type,
                new NewArray(region, args)
              ]));
              break;
            case 86:
              args = popMany(bc.argCount);
              push(new NewArray(region, args));
              break;
            case 85:
              var properties = [];
              for (var i = 0; i < bc.argCount; i++) {
                var value = pop();
                var key = pop();
                true;
                key = constant(Multiname.getPublicQualifiedName(key.value));
                properties.push(new KeyValuePair(key, value));
              }
              push(new NewObject(region, properties));
              break;
            case 87:
              push(new IR.ASNewActivation(constant(methodInfo)));
              break;
            case 88:
              callee = globalProperty('createClass');
              push(call(callee, null, [
                constant(classes[bc.index]),
                pop(),
                topScope()
              ]));
              break;
            default:
              unexpected('Not Implemented: ' + bc);
            }
            if (op === OP_debug || op === OP_debugfile || op === OP_debugline) {
              continue;
            }
            if (traceBuilder) {
              writer.writeLn(('state: ' + state.toString()).padRight(' ', 100) + ' : ' + bci + ', ' + bc.toString(this.abc));
            }
          }
          if (traceBuilder) {
            writer.leave(('< state: ' + state.toString()).padRight(' ', 100));
          }
          if (!stops) {
            stops = [];
            if (bc.position + 1 <= bytecodes.length) {
              stops.push({
                control: region,
                target: bytecodes[bc.position + 1],
                state: state
              });
            }
          }
          return stops;
        }
        var stop;
        if (stopPoints.length > 1) {
          var stopRegion = new Region(null);
          var stopValuePhi = new Phi(stopRegion, null);
          var stopStorePhi = new Phi(stopRegion, null);
          stopPoints.forEach(function (stopPoint) {
            stopRegion.predecessors.push(stopPoint.region);
            stopValuePhi.pushValue(stopPoint.value);
            stopStorePhi.pushValue(stopPoint.store);
          });
          stop = new Stop(stopRegion, stopStorePhi, stopValuePhi);
        } else {
          stop = new Stop(stopPoints[0].region, stopPoints[0].store, stopPoints[0].value);
        }
        return new DFG(stop);
      };
      return builder;
    }();
  function buildMethod(verifier, methodInfo, scope, hasDynamicScope) {
    true;
    true;
    true;
    Counter.count('Compiler: Compiled Methods');
    Timer.start('Compiler');
    Timer.start('Mark Loops');
    methodInfo.analysis.markLoops();
    Timer.stop();
    if (Shumway.AVM2.Runtime.enableVerifier.value) {
      Timer.start('Verify');
      verifier.verifyMethod(methodInfo, scope);
      Timer.stop();
    }
    var traceSource = c4TraceLevel.value > 0;
    var traceIR = c4TraceLevel.value > 1;
    Timer.start('Build IR');
    Node.startNumbering();
    var dfg = new Builder(methodInfo, scope, hasDynamicScope).buildGraph();
    Timer.stop();
    traceIR && dfg.trace(writer);
    Timer.start('Build CFG');
    var cfg = dfg.buildCFG();
    Timer.stop();
    Timer.start('Optimize Phis');
    cfg.optimizePhis();
    Timer.stop();
    Timer.start('Schedule Nodes');
    cfg.scheduleEarly();
    Timer.stop();
    traceIR && cfg.trace(writer);
    Timer.start('Verify IR');
    cfg.verify();
    Timer.stop();
    Timer.start('Allocate Variables');
    cfg.allocateVariables();
    Timer.stop();
    Timer.start('Generate Source');
    var result = Backend.generate(cfg, enableRegisterAllocator.value);
    Timer.stop();
    traceSource && writer.writeLn(result.body);
    Node.stopNumbering();
    Timer.stop();
    return result;
  }
  exports.buildMethod = buildMethod;
}(typeof exports === 'undefined' ? Builder = {} : exports));
var Compiler = new (function () {
    function constructor() {
      this.verifier = new Verifier();
    }
    constructor.prototype.compileMethod = function (methodInfo, scope, hasDynamicScope) {
      return Builder.buildMethod(this.verifier, methodInfo, scope, hasDynamicScope);
    };
    return constructor;
  }())();
(function (exports) {
  var Control = function () {
      var SEQ = 1;
      var LOOP = 2;
      var IF = 3;
      var CASE = 4;
      var SWITCH = 5;
      var LABEL_CASE = 6;
      var LABEL_SWITCH = 7;
      var EXIT = 8;
      var BREAK = 9;
      var CONTINUE = 10;
      var TRY = 11;
      var CATCH = 12;
      function Seq(body) {
        this.kind = SEQ;
        this.body = body;
      }
      Seq.prototype = {
        trace: function (writer) {
          var body = this.body;
          for (var i = 0, j = body.length; i < j; i++) {
            body[i].trace(writer);
          }
        },
        first: function () {
          return this.body[0];
        },
        slice: function (begin, end) {
          return new Seq(this.body.slice(begin, end));
        }
      };
      function Loop(body) {
        this.kind = LOOP;
        this.body = body;
      }
      Loop.prototype = {
        trace: function (writer) {
          writer.enter('loop {');
          this.body.trace(writer);
          writer.leave('}');
        }
      };
      function If(cond, then, els, nothingThrownLabel) {
        this.kind = IF;
        this.cond = cond;
        this.then = then;
        this.else = els;
        this.negated = false;
        this.nothingThrownLabel = nothingThrownLabel;
      }
      If.prototype = {
        trace: function (writer) {
          this.cond.trace(writer);
          if (this.nothingThrownLabel) {
            writer.enter('if (label is ' + this.nothingThrownLabel + ') {');
          }
          writer.enter('if' + (this.negated ? ' not' : '') + ' {');
          this.then && this.then.trace(writer);
          if (this.else) {
            writer.outdent();
            writer.enter('} else {');
            this.else.trace(writer);
          }
          writer.leave('}');
          if (this.nothingThrownLabel) {
            writer.leave('}');
          }
        }
      };
      function Case(index, body) {
        this.kind = CASE;
        this.index = index;
        this.body = body;
      }
      Case.prototype = {
        trace: function (writer) {
          if (this.index >= 0) {
            writer.writeLn('case ' + this.index + ':');
          } else {
            writer.writeLn('default:');
          }
          writer.indent();
          this.body && this.body.trace(writer);
          writer.outdent();
        }
      };
      function Switch(determinant, cases, nothingThrownLabel) {
        this.kind = SWITCH;
        this.determinant = determinant;
        this.cases = cases;
        this.nothingThrownLabel = nothingThrownLabel;
      }
      Switch.prototype = {
        trace: function (writer) {
          if (this.nothingThrownLabel) {
            writer.enter('if (label is ' + this.nothingThrownLabel + ') {');
          }
          this.determinant.trace(writer);
          writer.writeLn('switch {');
          for (var i = 0, j = this.cases.length; i < j; i++) {
            this.cases[i].trace(writer);
          }
          writer.writeLn('}');
          if (this.nothingThrownLabel) {
            writer.leave('}');
          }
        }
      };
      function LabelCase(labels, body) {
        this.kind = LABEL_CASE;
        this.labels = labels;
        this.body = body;
      }
      LabelCase.prototype = {
        trace: function (writer) {
          writer.enter('if (label is ' + this.labels.join(' or ') + ') {');
          this.body && this.body.trace(writer);
          writer.leave('}');
        }
      };
      function LabelSwitch(cases) {
        var labelMap = {};
        for (var i = 0, j = cases.length; i < j; i++) {
          var c = cases[i];
          if (!c.labels) {
            print(c.toSource());
          }
          for (var k = 0, l = c.labels.length; k < l; k++) {
            labelMap[c.labels[k]] = c;
          }
        }
        this.kind = LABEL_SWITCH;
        this.cases = cases;
        this.labelMap = labelMap;
      }
      LabelSwitch.prototype = {
        trace: function (writer) {
          for (var i = 0, j = this.cases.length; i < j; i++) {
            this.cases[i].trace(writer);
          }
        }
      };
      function Exit(label) {
        this.kind = EXIT;
        this.label = label;
      }
      Exit.prototype = {
        trace: function (writer) {
          writer.writeLn('label = ' + this.label);
        }
      };
      function Break(label, head) {
        this.kind = BREAK;
        this.label = label;
        this.head = head;
      }
      Break.prototype = {
        trace: function (writer) {
          this.label && writer.writeLn('label = ' + this.label);
          writer.writeLn('break');
        }
      };
      function Continue(label, head) {
        this.kind = CONTINUE;
        this.label = label;
        this.head = head;
        this.necessary = true;
      }
      Continue.prototype = {
        trace: function (writer) {
          this.label && writer.writeLn('label = ' + this.label);
          this.necessary && writer.writeLn('continue');
        }
      };
      function Try(body, catches) {
        this.kind = TRY;
        this.body = body;
        this.catches = catches;
      }
      Try.prototype = {
        trace: function (writer) {
          writer.enter('try {');
          this.body.trace(writer);
          writer.writeLn('label = ' + this.nothingThrownLabel);
          for (var i = 0, j = this.catches.length; i < j; i++) {
            this.catches[i].trace(writer);
          }
          writer.leave('}');
        }
      };
      function Catch(varName, typeName, body) {
        this.kind = CATCH;
        this.varName = varName;
        this.typeName = typeName;
        this.body = body;
      }
      Catch.prototype = {
        trace: function (writer) {
          writer.outdent();
          writer.enter('} catch (' + (this.varName || 'e') + (this.typeName ? ' : ' + this.typeName : '') + ') {');
          this.body.trace(writer);
        }
      };
      return {
        SEQ: SEQ,
        LOOP: LOOP,
        IF: IF,
        CASE: CASE,
        SWITCH: SWITCH,
        LABEL_CASE: LABEL_CASE,
        LABEL_SWITCH: LABEL_SWITCH,
        EXIT: EXIT,
        BREAK: BREAK,
        CONTINUE: CONTINUE,
        TRY: TRY,
        CATCH: CATCH,
        Seq: Seq,
        Loop: Loop,
        If: If,
        Case: Case,
        Switch: Switch,
        LabelCase: LabelCase,
        LabelSwitch: LabelSwitch,
        Exit: Exit,
        Break: Break,
        Continue: Continue,
        Try: Try,
        Catch: Catch
      };
    }();
  var Analysis = function () {
      function blockSetClass(length, blockById) {
        var BlockSet = BitSetFunctor(length);
        var ADDRESS_BITS_PER_WORD = BlockSet.ADDRESS_BITS_PER_WORD;
        var BITS_PER_WORD = BlockSet.BITS_PER_WORD;
        var BIT_INDEX_MASK = BlockSet.BIT_INDEX_MASK;
        BlockSet.singleton = function singleton(b) {
          var bs = new BlockSet();
          bs.set(b.id);
          bs.count = 1;
          bs.dirty = 0;
          return bs;
        };
        BlockSet.fromBlocks = function fromArray(other) {
          var bs = new BlockSet();
          bs.setBlocks(other);
          return bs;
        };
        var Bsp = BlockSet.prototype;
        if (BlockSet.singleword) {
          Bsp.forEachBlock = function forEach(fn) {
            true;
            var byId = blockById;
            var word = this.bits;
            if (word) {
              for (var k = 0; k < BITS_PER_WORD; k++) {
                if (word & 1 << k) {
                  fn(byId[k]);
                }
              }
            }
          };
          Bsp.choose = function choose() {
            var byId = blockById;
            var word = this.bits;
            if (word) {
              for (var k = 0; k < BITS_PER_WORD; k++) {
                if (word & 1 << k) {
                  return byId[k];
                }
              }
            }
          };
          Bsp.members = function members() {
            var byId = blockById;
            var set = [];
            var word = this.bits;
            if (word) {
              for (var k = 0; k < BITS_PER_WORD; k++) {
                if (word & 1 << k) {
                  set.push(byId[k]);
                }
              }
            }
            return set;
          };
          Bsp.setBlocks = function setBlocks(bs) {
            var bits = this.bits;
            for (var i = 0, j = bs.length; i < j; i++) {
              var id = bs[i].id;
              bits |= 1 << (id & BIT_INDEX_MASK);
            }
            this.bits = bits;
          };
        } else {
          Bsp.forEachBlock = function forEach(fn) {
            true;
            var byId = blockById;
            var bits = this.bits;
            for (var i = 0, j = bits.length; i < j; i++) {
              var word = bits[i];
              if (word) {
                for (var k = 0; k < BITS_PER_WORD; k++) {
                  if (word & 1 << k) {
                    fn(byId[i * BITS_PER_WORD + k]);
                  }
                }
              }
            }
          };
          Bsp.choose = function choose() {
            var byId = blockById;
            var bits = this.bits;
            for (var i = 0, j = bits.length; i < j; i++) {
              var word = bits[i];
              if (word) {
                for (var k = 0; k < BITS_PER_WORD; k++) {
                  if (word & 1 << k) {
                    return byId[i * BITS_PER_WORD + k];
                  }
                }
              }
            }
          };
          Bsp.members = function members() {
            var byId = blockById;
            var set = [];
            var bits = this.bits;
            for (var i = 0, j = bits.length; i < j; i++) {
              var word = bits[i];
              if (word) {
                for (var k = 0; k < BITS_PER_WORD; k++) {
                  if (word & 1 << k) {
                    set.push(byId[i * BITS_PER_WORD + k]);
                  }
                }
              }
            }
            return set;
          };
          Bsp.setBlocks = function setBlocks(bs) {
            var bits = this.bits;
            for (var i = 0, j = bs.length; i < j; i++) {
              var id = bs[i].id;
              bits[id >> ADDRESS_BITS_PER_WORD] |= 1 << (id & BIT_INDEX_MASK);
            }
          };
        }
        return BlockSet;
      }
      function Analysis(cfg, options) {
        this.options = options || {};
        this.BlockSet = blockSetClass(cfg.blocks.length, cfg.blocks);
        this.hasExceptions = false;
        this.normalizeReachableBlocks(cfg.root);
      }
      Analysis.prototype = {
        normalizeReachableBlocks: function normalizeReachableBlocks(root) {
          true;
          var ONCE = 1;
          var BUNCH_OF_TIMES = 2;
          var BlockSet = this.BlockSet;
          var blocks = [];
          var visited = {};
          var ancestors = {};
          var worklist = [
              root
            ];
          var node;
          ancestors[root.id] = true;
          while (node = worklist.top()) {
            if (visited[node.id]) {
              if (visited[node.id] === ONCE) {
                visited[node.id] = BUNCH_OF_TIMES;
                blocks.push(node);
              }
              ancestors[node.id] = false;
              worklist.pop();
              continue;
            }
            visited[node.id] = ONCE;
            ancestors[node.id] = true;
            var successors = node.successors;
            for (var i = 0, j = successors.length; i < j; i++) {
              var s = successors[i];
              if (ancestors[s.id]) {
                if (!node.spbacks) {
                  node.spbacks = new BlockSet();
                }
                node.spbacks.set(s.id);
              }
              !visited[s.id] && worklist.push(s);
            }
          }
          this.blocks = blocks.reverse();
        },
        computeDominance: function computeDominance() {
          function intersectDominators(doms, b1, b2) {
            var finger1 = b1;
            var finger2 = b2;
            while (finger1 !== finger2) {
              while (finger1 > finger2) {
                finger1 = doms[finger1];
              }
              while (finger2 > finger1) {
                finger2 = doms[finger2];
              }
            }
            return finger1;
          }
          var blocks = this.blocks;
          var n = blocks.length;
          var doms = new Array(n);
          doms[0] = 0;
          var rpo = [];
          for (var b = 0; b < n; b++) {
            rpo[blocks[b].id] = b;
            blocks[b].dominatees = [];
          }
          var changed = true;
          while (changed) {
            changed = false;
            for (var b = 1; b < n; b++) {
              var predecessors = blocks[b].predecessors;
              var j = predecessors.length;
              var newIdom = rpo[predecessors[0].id];
              if (!(newIdom in doms)) {
                for (var i = 1; i < j; i++) {
                  newIdom = rpo[predecessors[i].id];
                  if (newIdom in doms) {
                    break;
                  }
                }
              }
              true;
              for (var i = 0; i < j; i++) {
                var p = rpo[predecessors[i].id];
                if (p === newIdom) {
                  continue;
                }
                if (p in doms) {
                  newIdom = intersectDominators(doms, p, newIdom);
                }
              }
              if (doms[b] !== newIdom) {
                doms[b] = newIdom;
                changed = true;
              }
            }
          }
          blocks[0].dominator = blocks[0];
          var block;
          for (var b = 1; b < n; b++) {
            block = blocks[b];
            var idom = blocks[doms[b]];
            block.dominator = idom;
            idom.dominatees.push(block);
            block.npredecessors = block.predecessors.length;
          }
          var worklist = [
              blocks[0]
            ];
          blocks[0].level || (blocks[0].level = 0);
          while (block = worklist.shift()) {
            var dominatees = block.dominatees;
            for (var i = 0, j = dominatees.length; i < j; i++) {
              dominatees[i].level = block.level + 1;
            }
            worklist.push.apply(worklist, dominatees);
          }
        },
        computeFrontiers: function computeFrontiers() {
          var BlockSet = this.BlockSet;
          var blocks = this.blocks;
          for (var b = 0, n = blocks.length; b < n; b++) {
            blocks[b].frontier = new BlockSet();
          }
          for (var b = 1, n = blocks.length; b < n; b++) {
            var block = blocks[b];
            var predecessors = block.predecessors;
            if (predecessors.length >= 2) {
              var idom = block.dominator;
              for (var i = 0, j = predecessors.length; i < j; i++) {
                var runner = predecessors[i];
                while (runner !== idom) {
                  runner.frontier.set(block.id);
                  runner = runner.dominator;
                }
              }
            }
          }
        },
        analyzeControlFlow: function analyzeControlFlow() {
          this.computeDominance();
          this.analyzedControlFlow = true;
          return true;
        },
        markLoops: function markLoops() {
          if (!this.analyzedControlFlow && !this.analyzeControlFlow()) {
            return false;
          }
          var BlockSet = this.BlockSet;
          function findSCCs(root) {
            var preorderId = 1;
            var preorder = {};
            var assigned = {};
            var unconnectedNodes = [];
            var pendingNodes = [];
            var sccs = [];
            var level = root.level + 1;
            var worklist = [
                root
              ];
            var node;
            var u, s;
            while (node = worklist.top()) {
              if (preorder[node.id]) {
                if (pendingNodes.peek() === node) {
                  pendingNodes.pop();
                  var scc = [];
                  do {
                    u = unconnectedNodes.pop();
                    assigned[u.id] = true;
                    scc.push(u);
                  } while (u !== node);
                  if (scc.length > 1 || u.spbacks && u.spbacks.get(u.id)) {
                    sccs.push(scc);
                  }
                }
                worklist.pop();
                continue;
              }
              preorder[node.id] = preorderId++;
              unconnectedNodes.push(node);
              pendingNodes.push(node);
              var successors = node.successors;
              for (var i = 0, j = successors.length; i < j; i++) {
                s = successors[i];
                if (s.level < level) {
                  continue;
                }
                var sid = s.id;
                if (!preorder[sid]) {
                  worklist.push(s);
                } else if (!assigned[sid]) {
                  while (preorder[pendingNodes.peek().id] > preorder[sid]) {
                    pendingNodes.pop();
                  }
                }
              }
            }
            return sccs;
          }
          function findLoopHeads(blocks) {
            var heads = new BlockSet();
            for (var i = 0, j = blocks.length; i < j; i++) {
              var block = blocks[i];
              var spbacks = block.spbacks;
              if (!spbacks) {
                continue;
              }
              var successors = block.successors;
              for (var k = 0, l = successors.length; k < l; k++) {
                var s = successors[k];
                if (spbacks.get(s.id)) {
                  heads.set(s.dominator.id);
                }
              }
            }
            return heads.members();
          }
          function LoopInfo(scc, loopId) {
            var body = new BlockSet();
            body.setBlocks(scc);
            body.recount();
            this.id = loopId;
            this.body = body;
            this.exit = new BlockSet();
            this.save = {};
            this.head = new BlockSet();
            this.npredecessors = 0;
          }
          var heads = findLoopHeads(this.blocks);
          if (heads.length <= 0) {
            this.markedLoops = true;
            return true;
          }
          var worklist = heads.sort(function (a, b) {
              return a.level - b.level;
            });
          var loopId = 0;
          for (var n = worklist.length - 1; n >= 0; n--) {
            var top = worklist[n];
            var sccs = findSCCs(top);
            if (sccs.length === 0) {
              continue;
            }
            for (var i = 0, j = sccs.length; i < j; i++) {
              var scc = sccs[i];
              var loop = new LoopInfo(scc, loopId++);
              for (var k = 0, l = scc.length; k < l; k++) {
                var h = scc[k];
                if (h.level === top.level + 1 && !h.loop) {
                  h.loop = loop;
                  loop.head.set(h.id);
                  var predecessors = h.predecessors;
                  for (var pi = 0, pj = predecessors.length; pi < pj; pi++) {
                    loop.body.get(predecessors[pi].id) && h.npredecessors--;
                  }
                  loop.npredecessors += h.npredecessors;
                }
              }
              for (var k = 0, l = scc.length; k < l; k++) {
                var h = scc[k];
                if (h.level === top.level + 1) {
                  h.npredecessors = loop.npredecessors;
                }
              }
              loop.head.recount();
            }
          }
          this.markedLoops = true;
          return true;
        },
        induceControlTree: function induceControlTree() {
          var hasExceptions = this.hasExceptions;
          var BlockSet = this.BlockSet;
          function maybe(exit, save) {
            exit.recount();
            if (exit.count === 0) {
              return null;
            }
            exit.save = save;
            return exit;
          }
          var exceptionId = this.blocks.length;
          function induce(head, exit, save, loop, inLoopHead, lookupSwitch, fallthrough) {
            var v = [];
            while (head) {
              if (head.count > 1) {
                var exit2 = new BlockSet();
                var save2 = {};
                var cases = [];
                var heads = head.members();
                for (var i = 0, j = heads.length; i < j; i++) {
                  var h = heads[i];
                  var bid = h.id;
                  var c;
                  if (h.loop && head.contains(h.loop.head)) {
                    var loop2 = h.loop;
                    if (!loop2.induced) {
                      var lheads = loop2.head.members();
                      var lheadsave = 0;
                      for (k = 0, l = lheads.length; k < l; k++) {
                        lheadsave += head.save[lheads[k].id];
                      }
                      if (h.npredecessors - lheadsave > 0) {
                        h.npredecessors -= head.save[bid];
                        h.save = head.save[bid];
                        c = induce(h, exit2, save2, loop);
                        cases.push(new Control.LabelCase([
                          bid
                        ], c));
                      } else {
                        for (k = 0, l = lheads.length; k < l; k++) {
                          var lh = lheads[k];
                          lh.npredecessors -= lheadsave;
                          lh.save = lheadsave;
                        }
                        c = induce(h, exit2, save2, loop);
                        cases.push(new Control.LabelCase(loop2.head.toArray(), c));
                        loop2.induced = true;
                      }
                    }
                  } else {
                    h.npredecessors -= head.save[bid];
                    h.save = head.save[bid];
                    c = induce(h, exit2, save2, loop);
                    cases.push(new Control.LabelCase([
                      bid
                    ], c));
                  }
                }
                var pruned = [];
                var k = 0;
                var c;
                for (var i = 0, j = cases.length; i < j; i++) {
                  c = cases[i];
                  var labels = c.labels;
                  var lk = 0;
                  for (var ln = 0, nlabels = labels.length; ln < nlabels; ln++) {
                    var bid = labels[ln];
                    if (exit2.get(bid) && heads[i].npredecessors - head.save[bid] > 0) {
                      pruned.push(bid);
                    } else {
                      labels[lk++] = bid;
                    }
                  }
                  labels.length = lk;
                  if (labels.length > 0) {
                    cases[k++] = c;
                  }
                }
                cases.length = k;
                if (cases.length === 0) {
                  for (var i = 0, j = pruned.length; i < j; i++) {
                    var bid = pruned[i];
                    save[bid] = (save[bid] || 0) + head.save[bid];
                    exit.set(bid);
                  }
                  break;
                }
                v.push(new Control.LabelSwitch(cases));
                head = maybe(exit2, save2);
                continue;
              }
              var h, bid, c;
              if (head.count === 1) {
                h = head.choose();
                bid = h.id;
                h.npredecessors -= head.save[bid];
                h.save = head.save[bid];
              } else {
                h = head;
                bid = h.id;
              }
              if (inLoopHead) {
                inLoopHead = false;
              } else {
                if (loop && !loop.body.get(bid)) {
                  h.npredecessors += h.save;
                  loop.exit.set(bid);
                  loop.save[bid] = (loop.save[bid] || 0) + h.save;
                  v.push(new Control.Break(bid, loop));
                  break;
                }
                if (loop && h.loop === loop) {
                  h.npredecessors += h.save;
                  v.push(new Control.Continue(bid, loop));
                  break;
                }
                if (h === fallthrough) {
                  break;
                }
                if (h.npredecessors > 0) {
                  h.npredecessors += h.save;
                  save[bid] = (save[bid] || 0) + h.save;
                  exit.set(bid);
                  v.push(lookupSwitch ? new Control.Break(bid, lookupSwitch) : new Control.Exit(bid));
                  break;
                }
                if (h.loop) {
                  var l = h.loop;
                  var body;
                  if (l.head.count === 1) {
                    body = induce(l.head.choose(), null, null, l, true);
                  } else {
                    var lcases = [];
                    var lheads = l.head.members();
                    for (var i = 0, j = lheads.length; i < j; i++) {
                      var lh = lheads[i];
                      var lbid = lh.id;
                      var c = induce(lh, null, null, l, true);
                      lcases.push(new Control.LabelCase([
                        lbid
                      ], c));
                    }
                    body = new Control.LabelSwitch(lcases);
                  }
                  v.push(new Control.Loop(body));
                  head = maybe(l.exit, l.save);
                  continue;
                }
              }
              var sv;
              var successors;
              var exit2 = new BlockSet();
              var save2 = {};
              if (hasExceptions && h.hasCatches) {
                var allsuccessors = h.successors;
                var catchsuccessors = [];
                successors = [];
                for (var i = 0, j = allsuccessors.length; i < j; i++) {
                  var s = allsuccessors[i];
                  (s.exception ? catchsuccessors : successors).push(s);
                }
                var catches = [];
                for (var i = 0, j = catchsuccessors.length; i < j; i++) {
                  var t = catchsuccessors[i];
                  t.npredecessors -= 1;
                  t.save = 1;
                  var c = induce(t, exit2, save2, loop);
                  var ex = t.exception;
                  catches.push(new Control.Catch(ex.varName, ex.typeName, c));
                }
                sv = new Control.Try(h, catches);
              } else {
                successors = h.successors;
                sv = h;
              }
              if (successors.length > 2) {
                var cases = [];
                var targets = successors;
                for (var i = targets.length - 1; i >= 0; i--) {
                  var t = targets[i];
                  t.npredecessors -= 1;
                  t.save = 1;
                  c = induce(t, exit2, save2, loop, null, h, targets[i + 1]);
                  cases.unshift(new Control.Case(i, c));
                }
                cases.top().index = undefined;
                if (hasExceptions && h.hasCatches) {
                  sv.nothingThrownLabel = exceptionId;
                  sv = new Control.Switch(sv, cases, exceptionId++);
                } else {
                  sv = new Control.Switch(sv, cases);
                }
                head = maybe(exit2, save2);
              } else if (successors.length === 2) {
                var branch1 = h.hasFlippedSuccessors ? successors[1] : successors[0];
                var branch2 = h.hasFlippedSuccessors ? successors[0] : successors[1];
                branch1.npredecessors -= 1;
                branch1.save = 1;
                var c1 = induce(branch1, exit2, save2, loop);
                branch2.npredecessors -= 1;
                branch2.save = 1;
                var c2 = induce(branch2, exit2, save2, loop);
                if (hasExceptions && h.hasCatches) {
                  sv.nothingThrownLabel = exceptionId;
                  sv = new Control.If(sv, c1, c2, exceptionId++);
                } else {
                  sv = new Control.If(sv, c1, c2);
                }
                head = maybe(exit2, save2);
              } else {
                c = successors[0];
                if (c) {
                  if (hasExceptions && h.hasCatches) {
                    sv.nothingThrownLabel = c.id;
                    save2[c.id] = (save2[c.id] || 0) + 1;
                    exit2.set(c.id);
                    head = maybe(exit2, save2);
                  } else {
                    c.npredecessors -= 1;
                    c.save = 1;
                    head = c;
                  }
                } else {
                  if (hasExceptions && h.hasCatches) {
                    sv.nothingThrownLabel = -1;
                    head = maybe(exit2, save2);
                  } else {
                    head = c;
                  }
                }
              }
              v.push(sv);
            }
            if (v.length > 1) {
              return new Control.Seq(v);
            }
            return v[0];
          }
          var root = this.blocks[0];
          this.controlTree = induce(root, new BlockSet(), {});
        },
        restructureControlFlow: function restructureControlFlow() {
          Timer.start('Restructure Control Flow');
          if (!this.markedLoops && !this.markLoops()) {
            Timer.stop();
            return false;
          }
          this.induceControlTree();
          this.restructuredControlFlow = true;
          Timer.stop();
          return true;
        },
        trace: function (writer) {
          function bid(node) {
            return node.id;
          }
          function traceBlock(block) {
            if (!block.dominator) {
              writer.enter('block unreachable {');
            } else {
              writer.enter('block ' + block.id + (block.successors.length > 0 ? ' -> ' + block.successors.map(bid).join(',') : '') + ' {');
              writer.writeLn('npredecessors'.padRight(' ', 10) + block.npredecessors);
              writer.writeLn('idom'.padRight(' ', 10) + block.dominator.id);
              writer.writeLn('domcs'.padRight(' ', 10) + block.dominatees.map(bid).join(','));
              if (block.frontier) {
                writer.writeLn('frontier'.padRight(' ', 10) + '{' + block.frontier.toArray().join(',') + '}');
              }
              writer.writeLn('level'.padRight(' ', 10) + block.level);
            }
            if (block.loop) {
              writer.writeLn('loop'.padRight(' ', 10) + '{' + block.loop.body.toArray().join(',') + '}');
              writer.writeLn('  id'.padRight(' ', 10) + block.loop.id);
              writer.writeLn('  head'.padRight(' ', 10) + '{' + block.loop.head.toArray().join(',') + '}');
              writer.writeLn('  exit'.padRight(' ', 10) + '{' + block.loop.exit.toArray().join(',') + '}');
              writer.writeLn('  npredecessors'.padRight(' ', 10) + block.loop.npredecessors);
            }
            writer.writeLn('');
            if (block.position >= 0) {
              for (var bci = block.position; bci <= block.end.position; bci++) {
                writer.writeLn(('' + bci).padRight(' ', 5) + bytecodes[bci]);
              }
            } else {
              writer.writeLn('abstract');
            }
            writer.leave('}');
          }
          var bytecodes = this.bytecodes;
          writer.enter('analysis {');
          writer.enter('cfg {');
          this.blocks.forEach(traceBlock);
          writer.leave('}');
          if (this.controlTree) {
            writer.enter('control-tree {');
            this.controlTree.trace(writer);
            writer.leave('}');
          }
          writer.leave('}');
        },
        traceCFG: makeVizTrace([
          {
            fn: function (n) {
              return n.successors || [];
            },
            style: ''
          }
        ], [
          {
            fn: function (n) {
              return n.predecessors || [];
            },
            style: ''
          }
        ]),
        traceDJ: makeVizTrace([
          {
            fn: function (n) {
              return n.dominatees || [];
            },
            style: 'style=dashed'
          },
          {
            fn: function (n) {
              var crosses = new this.BlockSet();
              crosses.setBlocks(n.successors);
              crosses.subtract(this.BlockSet.fromBlocks(n.dominatees));
              n.spbacks && crosses.subtract(n.spbacks);
              return crosses.members();
            },
            style: ''
          },
          {
            fn: function (n) {
              return n.spbacks ? n.spbacks.members() : [];
            },
            style: 'style=bold'
          }
        ], [
          {
            fn: function (n) {
              return n.predecessors || [];
            },
            style: ''
          }
        ], function (idFn, writer) {
          var root = this.bytecodes[0];
          var worklist = [
              root
            ];
          var n;
          var level = root.level;
          var currentLevel = [];
          while (n = worklist.shift()) {
            if (level != n.level) {
              writer.writeLn('{rank=same; ' + currentLevel.map(function (n) {
                return 'block_' + idFn(n);
              }).join(' ') + '}');
              currentLevel.length = 0;
              level = n.level;
            }
            currentLevel.push(n);
            worklist.push.apply(worklist, n.dominatees);
          }
        })
      };
      function makeVizTrace(successorFns, predecessorFns, postHook) {
        return function (writer, name, prefix) {
          function idFn(n) {
            return prefix + n.id;
          }
          var analysis = this;
          function bindToThis(x) {
            x.fn = x.fn.bind(analysis);
          }
          prefix = prefix || '';
          var bytecodes = this.bytecodes;
          if (!bytecodes) {
            return;
          }
          successorFns.forEach(bindToThis);
          predecessorFns.forEach(bindToThis);
          writeGraphViz(writer, name.toString(), bytecodes[0], idFn, function (n) {
            return n.successors || [];
          }, successorFns, predecessorFns, function (n) {
            var str = 'Block: ' + n.id + '\\l';
            return str;
          }, postHook && postHook.bind(this, idFn));
        };
      }
      return Analysis;
    }();
  exports.Control = Control;
  exports.analyze = function (cfg) {
    var analysis = new Analysis(cfg);
    analysis.restructureControlFlow();
    return analysis.controlTree;
  };
}(typeof exports === 'undefined' ? Looper = {} : exports));
(function (exports) {
  var TRACE_REGISTER_ALLOCATOR = false;
  var T = estransform;
  var Node = T.Node;
  var Identifier = T.Identifier;
  var VariableDeclaration = T.VariableDeclaration;
  var VariableDeclarator = T.VariableDeclarator;
  var AssignmentExpression = T.AssignmentExpression;
  var MemberExpression = T.MemberExpression;
  var IfStatement = T.IfStatement;
  var WhileStatement = T.WhileStatement;
  var FunctionDeclaration = T.FunctionDeclaration;
  var writer = new IndentingWriter();
  var LinearScan = function () {
      function Interval(id, start, end) {
        this.id = id;
        this.start = start;
        this.end = end;
      }
      Interval.prototype.toString = function () {
        return '[' + this.start + ',' + this.end + ']';
      };
      function linearScan(intervals, maxRegisters) {
        this.intervals = intervals.slice(0);
        this.maxRegisters = maxRegisters;
      }
      linearScan.prototype.allocate = function () {
        var intervals = this.intervals;
        this.intervals.sort(function (a, b) {
          return a.start - b.start;
        });
        var active = new SortedList(function (a, b) {
            return a.end - b.end;
          });
        var maxRegisters = this.maxRegisters;
        var freeRegisters = [];
        for (var i = maxRegisters - 1; i >= 0; i--) {
          freeRegisters.push('R' + i);
        }
        intervals.forEach(function (i) {
          expireOldIntervals(i);
          if (active.length === maxRegisters) {
            notImplemented('Cannot Spill');
          } else {
            i.register = freeRegisters.pop();
            TRACE_REGISTER_ALLOCATOR && writer.writeLn('Allocate: ' + i + ' ' + i.id + ' -> ' + i.register);
            active.push(i);
          }
        });
        function expireOldIntervals(i) {
          active.forEach(function (j) {
            if (j.end >= i.start) {
              return SortedList.RETURN;
            }
            freeRegisters.push(j.register);
            TRACE_REGISTER_ALLOCATOR && writer.writeLn('Release: ' + j + ' -> ' + j.register);
            return SortedList.DELETE;
          });
        }
      };
      linearScan.Interval = Interval;
      return linearScan;
    }();
  function allocateRegisters(program) {
    var scan = T.makePass('scan', 'scanNode');
    var label = 0;
    Node.prototype.scan = function (o) {
      this.position = label++;
      return scan.apply(this, o);
    };
    var variables = [];
    var variableIndexMap = {};
    var identifiers = [];
    FunctionDeclaration.prototype.scan = function () {
      this.params.forEach(function (identifier) {
        if (!(identifier.name in variableIndexMap)) {
          variableIndexMap[identifier.name] = variables.length;
          variables.push(identifier.name);
        }
      });
      this.body.scan();
      return this;
    };
    VariableDeclarator.prototype.scan = function () {
      this.position = label++;
      if (!(this.id.name in variableIndexMap)) {
        variableIndexMap[this.id.name] = variables.length;
        variables.push(this.id.name);
      }
      return this;
    };
    AssignmentExpression.prototype.scan = function (o) {
      this.left.scan(o);
      this.right.scan(o);
      this.position = label++;
      return this;
    };
    WhileStatement.prototype.scan = function (o) {
      this.position = label++;
      this.test.scan(o);
      this.body.scan(o);
      this.afterPosition = label++;
      return this;
    };
    program.scan();
    TRACE_REGISTER_ALLOCATOR && writer.writeLn('Local Variables: ' + variables);
    var Set = BitSetFunctor(variables.length);
    var Range = BitSetFunctor(label);
    var ranges = [];
    for (var i = 0; i < variables.length; i++) {
      ranges.push(new Range());
    }
    function fill(range) {
      var start = -1;
      for (var i = 0; i < range.length; i++) {
        if (range.get(i)) {
          start = i;
          break;
        }
      }
      for (var i = range.length - 1; i >= 0; i--) {
        if (range.get(i)) {
          end = i;
          break;
        }
      }
      for (var i = start; i < end; i++) {
        range.set(i);
      }
    }
    function getRange(range) {
      var start = -1, end = -1;
      for (var i = 0; i < range.length; i++) {
        if (range.get(i)) {
          start = i;
          break;
        }
      }
      for (var i = range.length - 1; i >= 0; i--) {
        if (range.get(i)) {
          end = i;
          break;
        }
      }
      return [
        start,
        end
      ];
    }
    function use(set, name, position) {
      var index = variableIndexMap[name];
      ranges[index].set(position);
      set.set(index);
    }
    function def(set, name, position) {
      var index = variableIndexMap[name];
      ranges[index].set(position);
      set.clear(index);
    }
    Node.prototype.markLiveness = T.makePass('markLiveness', 'markLivenessNode', true);
    Identifier.prototype.markLiveness = function (o) {
      var name = this.name;
      if (name === 'undefined') {
        return this;
      }
      if (o && o.isProperty) {
        return this;
      }
      if (!(name in variableIndexMap)) {
        return this;
      }
      identifiers.push(this);
      var live = o.live;
      use(live, name, this.position);
      return this;
    };
    VariableDeclarator.prototype.markLiveness = function (o) {
      var live = o.live;
      identifiers.push(this.id);
      return this;
    };
    IfStatement.prototype.markLiveness = function (o) {
      var a = o.live.clone();
      var b = o.live.clone();
      this.alternate && this.alternate.markLiveness({
        live: a
      });
      this.consequent && this.consequent.markLiveness({
        live: b
      });
      o.live.assign(a);
      o.live._union(b);
      this.test.markLiveness(o);
      return this;
    };
    WhileStatement.prototype.markLiveness = function (o) {
      var a = o.live.clone();
      TRACE_REGISTER_ALLOCATOR && writer.writeLn('END OF LOOP: ' + a);
      var afterPosition = this.afterPosition;
      do {
        var b = a.clone();
        this.body.markLiveness({
          live: a
        });
        this.test.markLiveness({
          live: a
        });
        TRACE_REGISTER_ALLOCATOR && writer.writeLn('TOP OF LOOP: ' + a);
        var iterate = !b.equals(a);
        if (iterate) {
          TRACE_REGISTER_ALLOCATOR && writer.writeLn('ITERATE');
          a.forEach(function (i) {
            ranges[i].set(afterPosition);
          });
        }
      } while (iterate);
      o.live.assign(a);
      return this;
    };
    AssignmentExpression.prototype.markLiveness = function (o) {
      this.right.markLiveness(o);
      if (this.left instanceof Identifier) {
        def(o.live, this.left.name, this.position);
        identifiers.push(this.left);
      } else {
        this.left.markLiveness(o);
      }
      return this;
    };
    MemberExpression.prototype.markLiveness = function (o) {
      if (this.computed || !(this.property instanceof Identifier)) {
        this.property.markLiveness(o);
      }
      this.object.markLiveness(o);
      return this;
    };
    program.markLiveness({
      live: new Set()
    });
    var intervals = [];
    for (var i = 0; i < ranges.length; i++) {
      var r = getRange(ranges[i]);
      intervals.push(new LinearScan.Interval(i, r[0], r[1]));
    }
    var allocator = new LinearScan(intervals, 1024);
    allocator.allocate();
    var map = createEmptyObject();
    for (var i = 0; i < variables.length; i++) {
      map[variables[i]] = intervals[i].register;
    }
    if (true) {
      for (var i = 0; i < identifiers.length; i++) {
        if (identifiers[i].patched) {
          continue;
        }
        identifiers[i].name = map[identifiers[i].name];
        identifiers[i].patched = true;
      }
    }
    if (TRACE_REGISTER_ALLOCATOR) {
      for (var i = 0; i < ranges.length; i++) {
        fill(ranges[i]);
        writer.writeLn(String(i).padLeft(' ', 3) + ' ' + variables[i].padRight(' ', 5) + ': ' + ranges[i].toBitString('=', ' ') + ' ' + intervals[i].register);
      }
    }
    return program;
  }
  Transform.transform = function (program) {
    allocateRegisters(program);
  };
}(typeof exports === 'undefined' ? Transform = {} : exports));
(function (exports) {
  var T = estransform;
  var Literal = T.Literal;
  var Identifier = T.Identifier;
  var VariableDeclaration = T.VariableDeclaration;
  var VariableDeclarator = T.VariableDeclarator;
  var MemberExpression = T.MemberExpression;
  var BinaryExpression = T.BinaryExpression;
  var CallExpression = T.CallExpression;
  var AssignmentExpression = T.AssignmentExpression;
  var ExpressionStatement = T.ExpressionStatement;
  var ReturnStatement = T.ReturnStatement;
  var FunctionDeclaration = T.FunctionDeclaration;
  var ConditionalExpression = T.ConditionalExpression;
  var ObjectExpression = T.ObjectExpression;
  var ArrayExpression = T.ArrayExpression;
  var UnaryExpression = T.UnaryExpression;
  var NewExpression = T.NewExpression;
  var Property = T.Property;
  var BlockStatement = T.BlockStatement;
  var ThisExpression = T.ThisExpression;
  var ThrowStatement = T.ThrowStatement;
  var IfStatement = T.IfStatement;
  var WhileStatement = T.WhileStatement;
  var BreakStatement = T.BreakStatement;
  var ContinueStatement = T.ContinueStatement;
  var SwitchStatement = T.SwitchStatement;
  var SwitchCase = T.SwitchCase;
  var Block = IR.Block;
  var Operator = IR.Operator;
  var Projection = IR.Projection;
  var Start = IR.Start;
  var Control = Looper.Control;
  var Variable = IR.Variable;
  Control.Break.prototype.compile = function (cx, state) {
    return cx.compileBreak(this, state);
  };
  Control.Continue.prototype.compile = function (cx, state) {
    return cx.compileContinue(this, state);
  };
  Control.Exit.prototype.compile = function (cx, state) {
    return cx.compileExit(this, state);
  };
  Control.LabelSwitch.prototype.compile = function (cx, state) {
    return cx.compileLabelSwitch(this, state);
  };
  Control.Seq.prototype.compile = function (cx, state) {
    return cx.compileSequence(this, state);
  };
  Block.prototype.compile = function (cx, state) {
    return cx.compileBlock(this, state);
  };
  Control.Loop.prototype.compile = function (cx, state) {
    return cx.compileLoop(this, state);
  };
  Control.Switch.prototype.compile = function (cx, state) {
    return cx.compileSwitch(this, state);
  };
  Control.If.prototype.compile = function (cx, state) {
    return cx.compileIf(this, state);
  };
  Control.Try.prototype.compile = function (cx, state) {
    return cx.compileTry(this, state);
  };
  function constant(value) {
    if (typeof value === 'string' || value === null || value === true || value === false) {
      return new Literal(value);
    } else if (value === undefined) {
      return new Identifier('undefined');
    } else if (typeof value === 'object' || typeof value === 'function') {
      return new Identifier(objectConstantName(value));
    } else if (typeof value === 'number' && isNaN(value)) {
      return new Identifier('NaN');
    } else if (value === Infinity) {
      return new Identifier('Infinity');
    } else if (value === -Infinity) {
      return new UnaryExpression('-', new Identifier('Infinity'));
    } else if (typeof value === 'number' && 1 / value < 0) {
      return new UnaryExpression('-', new Literal(Math.abs(value)));
    } else if (typeof value === 'number') {
      return new Literal(value);
    } else {
      unexpected('Cannot emit constant for value: ', value);
    }
  }
  function id(name) {
    true;
    return new Identifier(name);
  }
  function isIdentifierStart(c) {
    return c === '$' || c === '_' || c === '\\' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z';
  }
  function isIdentifierPart(c) {
    return c === '$' || c === '_' || c === '\\' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9';
  }
  function isIdentifierName(s) {
    if (!isIdentifierStart(s[0])) {
      return false;
    }
    for (var i = 1; i < s.length; i++) {
      if (!isIdentifierPart(s[i])) {
        return false;
      }
    }
    return true;
  }
  function property(obj) {
    for (var i = 1; i < arguments.length; i++) {
      var x = arguments[i];
      if (typeof x === 'string') {
        if (isIdentifierName(x)) {
          obj = new MemberExpression(obj, new Identifier(x), false);
        } else {
          obj = new MemberExpression(obj, new Literal(x), true);
        }
      } else if (x instanceof Literal && isIdentifierName(x.value)) {
        obj = new MemberExpression(obj, new Identifier(x.value), false);
      } else {
        obj = new MemberExpression(obj, x, true);
      }
    }
    return obj;
  }
  function call(callee, args) {
    true;
    true;
    return new CallExpression(callee, args);
  }
  function callCall(callee, object, args) {
    return call(property(callee, 'call'), [
      object
    ].concat(args));
  }
  function assignment(left, right) {
    true;
    return new AssignmentExpression(left, '=', right);
  }
  function variableDeclaration(declarations) {
    return new VariableDeclaration('var', declarations);
  }
  function negate(node) {
    if (node instanceof Constant) {
      if (node.value === true || node.value === false) {
        return constant(!node.value);
      }
    } else if (node instanceof Identifier) {
      return new UnaryExpression(Operator.FALSE.name, node);
    }
    true;
    var left = node instanceof BinaryExpression ? node.left : node.argument;
    var right = node.right;
    var operator = Operator.fromName(node.operator);
    if (operator === Operator.EQ && right instanceof Literal && right.value === false) {
      return left;
    }
    if (operator === Operator.FALSE) {
      return left;
    }
    if (operator.not) {
      if (node instanceof BinaryExpression) {
        return new BinaryExpression(operator.not.name, left, right);
      } else {
        return new UnaryExpression(operator.not.name, left);
      }
    }
    return new UnaryExpression(Operator.FALSE.name, node);
  }
  function Context() {
    this.label = new Variable('$L');
    this.variables = [];
    this.parameters = [];
  }
  Context.prototype.useVariable = function (variable) {
    true;
    return this.variables.pushUnique(variable);
  };
  Context.prototype.useParameter = function (parameter) {
    return this.parameters[parameter.index] = parameter;
  };
  Context.prototype.compileLabelBody = function compileLabelBody(node) {
    var body = [];
    if (node.label !== undefined) {
      this.useVariable(this.label);
      body.push(new ExpressionStatement(assignment(id(this.label.name), new Literal(node.label))));
    }
    return body;
  };
  Context.prototype.compileBreak = function compileBreak(node) {
    var body = this.compileLabelBody(node);
    body.push(new BreakStatement(null));
    return new BlockStatement(body);
  };
  Context.prototype.compileContinue = function compileContinue(node) {
    var body = this.compileLabelBody(node);
    body.push(new ContinueStatement(null));
    return new BlockStatement(body);
  };
  Context.prototype.compileExit = function compileExit(node) {
    return new BlockStatement(this.compileLabelBody(node));
  };
  Context.prototype.compileIf = function compileIf(node) {
    var cr = node.cond.compile(this);
    var tr = null, er = null;
    if (node.then) {
      tr = node.then.compile(this);
    }
    if (node.else) {
      er = node.else.compile(this);
    }
    var condition = compileValue(cr.end.predicate, this);
    condition = node.negated ? negate(condition) : condition;
    cr.body.push(new IfStatement(condition, tr || new BlockStatement([]), er || null));
    return cr;
  };
  Context.prototype.compileSwitch = function compileSwitch(node) {
    var dr = node.determinant.compile(this);
    var cases = [];
    node.cases.forEach(function (x) {
      var br;
      if (x.body) {
        br = x.body.compile(this);
      }
      var test = typeof x.index === 'number' ? new Literal(x.index) : undefined;
      cases.push(new SwitchCase(test, br ? [
        br
      ] : []));
    }, this);
    var determinant = compileValue(dr.end.determinant, this);
    dr.body.push(new SwitchStatement(determinant, cases, false));
    return dr;
  };
  Context.prototype.compileLabelSwitch = function compileLabelSwitch(node) {
    var statement = null;
    var labelName = id(this.label.name);
    function compileLabelTest(labelID) {
      true;
      return new BinaryExpression('===', labelName, new Literal(labelID));
    }
    for (var i = node.cases.length - 1; i >= 0; i--) {
      var c = node.cases[i];
      var labels = c.labels;
      var labelTest = compileLabelTest(labels[0]);
      for (var j = 1; j < labels.length; j++) {
        labelTest = new BinaryExpression('||', labelTest, compileLabelTest(labels[j]));
      }
      statement = new IfStatement(labelTest, c.body ? c.body.compile(this) : new BlockStatement(), statement);
    }
    return statement;
  };
  Context.prototype.compileLoop = function compileLoop(node) {
    var br = node.body.compile(this);
    return new WhileStatement(constant(true), br);
  };
  Context.prototype.compileSequence = function compileSequence(node) {
    var cx = this;
    var body = [];
    node.body.forEach(function (x) {
      var result = x.compile(cx);
      if (result instanceof BlockStatement) {
        body = body.concat(result.body);
      } else {
        body.push(result);
      }
    });
    return new BlockStatement(body);
  };
  Context.prototype.compileBlock = function compileBlock(block) {
    var body = [];
    for (var i = 1; i < block.nodes.length - 1; i++) {
      var node = block.nodes[i];
      var statement;
      var to;
      var from;
      if (node instanceof IR.Throw) {
        statement = compileValue(node, this, true);
      } else {
        if (node instanceof IR.Move) {
          to = id(node.to.name);
          this.useVariable(node.to);
          from = compileValue(node.from, this);
        } else {
          if (node.variable) {
            to = id(node.variable.name);
            this.useVariable(node.variable);
          } else {
            to = null;
          }
          from = compileValue(node, this, true);
        }
        if (to) {
          statement = new ExpressionStatement(assignment(to, from));
        } else {
          statement = new ExpressionStatement(from);
        }
      }
      body.push(statement);
    }
    var end = block.nodes.last();
    if (end instanceof IR.Stop) {
      body.push(new ReturnStatement(compileValue(end.argument, this)));
    }
    var result = new BlockStatement(body);
    result.end = block.nodes.last();
    true;
    return result;
  };
  function compileValue(value, cx, noVariable) {
    true;
    true;
    true;
    true;
    if (noVariable || !value.variable) {
      var node = value.compile(cx);
      return node;
    }
    true;
    return id(value.variable.name);
  }
  function compileMultiname(name, cx) {
    return [
      compileValue(name.namespaces, cx),
      compileValue(name.name, cx),
      constant(name.flags)
    ];
  }
  function isArray(array) {
    return array instanceof Array;
  }
  function compileValues(values, cx) {
    true;
    return values.map(function (value) {
      return compileValue(value, cx);
    });
  }
  IR.Parameter.prototype.compile = function (cx) {
    cx.useParameter(this);
    return id(this.name);
  };
  IR.Constant.prototype.compile = function (cx) {
    return constant(this.value);
  };
  IR.Variable.prototype.compile = function (cx) {
    return id(this.name);
  };
  IR.Phi.prototype.compile = function (cx) {
    true;
    return compileValue(this.variable, cx);
  };
  IR.ASScope.prototype.compile = function (cx) {
    var parent = compileValue(this.parent, cx);
    var object = compileValue(this.object, cx);
    var isWith = new Literal(this.isWith);
    return new NewExpression(id('Scope'), [
      parent,
      object,
      isWith
    ]);
  };
  IR.ASFindProperty.prototype.compile = function (cx) {
    var scope = compileValue(this.scope, cx);
    var name = compileMultiname(this.name, cx);
    var domain = compileValue(this.domain, cx);
    var strict = new Literal(this.strict);
    return call(property(scope, 'findScopeProperty'), name.concat([
      domain,
      strict
    ]));
  };
  IR.ASGetProperty.prototype.compile = function (cx) {
    var object = compileValue(this.object, cx);
    if (this.flags & IR.Flags.INDEXED) {
      true;
      return call(property(object, 'asGetNumericProperty'), [
        compileValue(this.name.name, cx)
      ]);
    } else if (this.flags & IR.Flags.RESOLVED) {
      return call(property(object, 'asGetResolvedStringProperty'), [
        compileValue(this.name, cx)
      ]);
    }
    var name = compileMultiname(this.name, cx);
    var isMethod = new Literal(this.flags & IR.Flags.IS_METHOD);
    return call(property(object, 'asGetProperty'), name.concat(isMethod));
  };
  IR.ASGetSuper.prototype.compile = function (cx) {
    var scope = compileValue(this.scope, cx);
    var object = compileValue(this.object, cx);
    var name = compileMultiname(this.name, cx);
    return call(property(object, 'asGetSuper'), [
      scope
    ].concat(name));
  };
  IR.Latch.prototype.compile = function (cx) {
    return new ConditionalExpression(compileValue(this.condition, cx), compileValue(this.left, cx), compileValue(this.right, cx));
  };
  IR.Unary.prototype.compile = function (cx) {
    return new UnaryExpression(this.operator.name, compileValue(this.argument, cx));
  };
  IR.Copy.prototype.compile = function (cx) {
    return compileValue(this.argument, cx);
  };
  IR.Binary.prototype.compile = function (cx) {
    var left = compileValue(this.left, cx);
    var right = compileValue(this.right, cx);
    if (this.operator === Operator.AS_ADD) {
      return call(id('asAdd'), [
        left,
        right
      ]);
    }
    return new BinaryExpression(this.operator.name, left, right);
  };
  IR.CallProperty.prototype.compile = function (cx) {
    var object = compileValue(this.object, cx);
    var name = compileValue(this.name, cx);
    var callee = property(object, name);
    var args = this.args.map(function (arg) {
        return compileValue(arg, cx);
      });
    if (this.flags & IR.Flags.PRISTINE) {
      return call(callee, args);
    } else {
      return callCall(callee, object, args);
    }
  };
  IR.ASCallProperty.prototype.compile = function (cx) {
    var object = compileValue(this.object, cx);
    var args = this.args.map(function (arg) {
        return compileValue(arg, cx);
      });
    if (this.flags & IR.Flags.RESOLVED) {
      return call(property(object, 'asCallResolvedStringProperty'), [
        compileValue(this.name, cx),
        new Literal(this.isLex),
        new ArrayExpression(args)
      ]);
    }
    var name = compileMultiname(this.name, cx);
    return call(property(object, 'asCallProperty'), name.concat([
      new Literal(this.isLex),
      new ArrayExpression(args)
    ]));
  };
  IR.ASCallSuper.prototype.compile = function (cx) {
    var scope = compileValue(this.scope, cx);
    var object = compileValue(this.object, cx);
    var args = this.args.map(function (arg) {
        return compileValue(arg, cx);
      });
    var name = compileMultiname(this.name, cx);
    return call(property(object, 'asCallSuper'), [
      scope
    ].concat(name).concat(new ArrayExpression(args)));
  };
  IR.Call.prototype.compile = function (cx) {
    var args = this.args.map(function (arg) {
        return compileValue(arg, cx);
      });
    var callee = compileValue(this.callee, cx);
    var object;
    if (this.object) {
      object = compileValue(this.object, cx);
    } else {
      object = new Literal(null);
    }
    if (false && this.pristine && (this.callee instanceof IR.GetProperty && this.callee.object === this.object) || this.object === null) {
      return call(callee, args);
    } else {
      return callCall(callee, object, args);
    }
  };
  IR.ASNew.prototype.compile = function (cx) {
    var args = this.args.map(function (arg) {
        return compileValue(arg, cx);
      });
    var callee = compileValue(this.callee, cx);
    callee = property(callee, 'instanceConstructor');
    return new NewExpression(callee, args);
  };
  IR.This.prototype.compile = function (cx) {
    return new ThisExpression();
  };
  IR.Throw.prototype.compile = function (cx) {
    var argument = compileValue(this.argument, cx);
    return new ThrowStatement(argument);
  };
  IR.Arguments.prototype.compile = function (cx) {
    return id('arguments');
  };
  IR.ASGlobal.prototype.compile = function (cx) {
    var scope = compileValue(this.scope, cx);
    return property(scope, 'global', 'object');
  };
  IR.ASSetProperty.prototype.compile = function (cx) {
    var object = compileValue(this.object, cx);
    var value = compileValue(this.value, cx);
    if (this.flags & IR.Flags.INDEXED) {
      return call(property(object, 'asSetNumericProperty'), [
        compileValue(this.name.name, cx),
        value
      ]);
    }
    var name = compileMultiname(this.name, cx);
    return call(property(object, 'asSetProperty'), name.concat(value));
  };
  IR.ASSetSuper.prototype.compile = function (cx) {
    var scope = compileValue(this.scope, cx);
    var object = compileValue(this.object, cx);
    var name = compileMultiname(this.name, cx);
    var value = compileValue(this.value, cx);
    return call(property(object, 'asSetSuper'), [
      scope
    ].concat(name).concat([
      value
    ]));
  };
  IR.ASDeleteProperty.prototype.compile = function (cx) {
    var object = compileValue(this.object, cx);
    var name = compileMultiname(this.name, cx);
    return call(property(object, 'asDeleteProperty'), name);
  };
  IR.ASHasProperty.prototype.compile = function (cx) {
    var object = compileValue(this.object, cx);
    var name = compileMultiname(this.name, cx);
    return call(property(object, 'asHasProperty'), name);
  };
  IR.GlobalProperty.prototype.compile = function (cx) {
    return id(this.name);
  };
  IR.GetProperty.prototype.compile = function (cx) {
    var object = compileValue(this.object, cx);
    var name = compileValue(this.name, cx);
    return property(object, name);
  };
  IR.SetProperty.prototype.compile = function (cx) {
    var object = compileValue(this.object, cx);
    var name = compileValue(this.name, cx);
    var value = compileValue(this.value, cx);
    return assignment(property(object, name), value);
  };
  IR.ASGetDescendants.prototype.compile = function (cx) {
    var object = compileValue(this.object, cx);
    var name = compileValue(this.name, cx);
    return call(id('getDescendants'), [
      object,
      name
    ]);
  };
  IR.ASSetSlot.prototype.compile = function (cx) {
    var object = compileValue(this.object, cx);
    var name = compileValue(this.name, cx);
    var value = compileValue(this.value, cx);
    return call(id('asSetSlot'), [
      object,
      name,
      value
    ]);
  };
  IR.ASGetSlot.prototype.compile = function (cx) {
    var object = compileValue(this.object, cx);
    var name = compileValue(this.name, cx);
    return call(id('asGetSlot'), [
      object,
      name
    ]);
  };
  IR.Projection.prototype.compile = function (cx) {
    true;
    true;
    return compileValue(this.argument.scope, cx);
  };
  IR.NewArray.prototype.compile = function (cx) {
    return new ArrayExpression(compileValues(this.elements, cx));
  };
  IR.NewObject.prototype.compile = function (cx) {
    var properties = this.properties.map(function (property) {
        var key = compileValue(property.key, cx);
        var value = compileValue(property.value, cx);
        return new Property(key, value, 'init');
      });
    return new ObjectExpression(properties);
  };
  IR.ASNewActivation.prototype.compile = function (cx) {
    var methodInfo = compileValue(this.methodInfo, cx);
    return call(id('asCreateActivation'), [
      methodInfo
    ]);
  };
  IR.ASMultiname.prototype.compile = function (cx) {
    var namespaces = compileValue(this.namespaces, cx);
    var name = compileValue(this.name, cx);
    return call(id('createName'), [
      namespaces,
      name
    ]);
  };
  function generateSource(node) {
    return escodegen.generate(node, {
      base: '',
      indent: '  ',
      comment: true,
      format: {
        compact: false
      }
    });
  }
  function generate(cfg, useRegisterAllocator) {
    Timer.start('Looper');
    var root = Looper.analyze(cfg);
    Timer.stop();
    var writer = new IndentingWriter();
    var cx = new Context();
    Timer.start('Construct AST');
    var code = root.compile(cx);
    Timer.stop();
    var parameters = [];
    for (var i = 0; i < cx.parameters.length; i++) {
      var name = cx.parameters[i] ? cx.parameters[i].name : '_' + i;
      parameters.push(id(name));
    }
    if (cx.variables.length) {
      Counter.count('Backend: Locals', cx.variables.length);
      var variables = variableDeclaration(cx.variables.map(function (variable) {
          return new VariableDeclarator(id(variable.name));
        }));
      code.body.unshift(variables);
    }
    var node = new FunctionDeclaration(id('fn'), parameters, code);
    if (useRegisterAllocator) {
      if (c4TraceLevel.value > 0) {
        writer.writeLn('=== BEFORE ===============================');
        writer.writeLn(generateSource(node));
        writer.writeLn('=== TRANSFORMING =========================');
      }
      Transform.transform(node);
      if (c4TraceLevel.value > 0) {
        writer.writeLn('=== AFTER ================================');
        writer.writeLn(generateSource(node));
        writer.writeLn('==========================================');
      }
      var body = generateSource(code);
      return {
        parameters: parameters.map(function (p) {
          return p.name;
        }),
        body: body
      };
    }
    Timer.start('Serialize AST');
    var source = generateSource(code);
    Timer.stop();
    return {
      parameters: parameters.map(function (p) {
        return p.name;
      }),
      body: source
    };
  }
  Backend.generate = generate;
}(typeof exports === 'undefined' ? Backend = {} : exports));
var Shumway;
(function (Shumway) {
  (function (AVM2) {
    (function (Runtime) {
      var Multiname = Shumway.AVM2.ABC.Multiname;
      var Namespace = Shumway.AVM2.ABC.Namespace;
      var ClassInfo = Shumway.AVM2.ABC.ClassInfo;
      var InstanceInfo = Shumway.AVM2.ABC.InstanceInfo;
      var Trait = Shumway.AVM2.ABC.Trait;
      var IndentingWriter = Shumway.IndentingWriter;
      var createMap = Shumway.ObjectUtilities.createMap;
      var defineNonEnumerableGetterOrSetter = Shumway.ObjectUtilities.defineNonEnumerableGetterOrSetter;
      var defineNonEnumerableProperty = Shumway.ObjectUtilities.defineNonEnumerableProperty;
      var defineReadOnlyProperty = Shumway.ObjectUtilities.defineReadOnlyProperty;
      var bindSafely = Shumway.FunctionUtilities.bindSafely;
      var vmNextTrampolineId = 1;
      var vmNextMemoizerId = 1;
      function getMethodOverrideKey(methodInfo) {
        var key;
        if (methodInfo.holder instanceof ClassInfo) {
          key = 'static ' + methodInfo.holder.instanceInfo.name.getOriginalName() + '::' + methodInfo.name.getOriginalName();
        } else if (methodInfo.holder instanceof InstanceInfo) {
          key = methodInfo.holder.name.getOriginalName() + '::' + methodInfo.name.getOriginalName();
        } else {
          key = methodInfo.name.getOriginalName();
        }
        return key;
      }
      Runtime.getMethodOverrideKey = getMethodOverrideKey;
      function checkMethodOverrides(methodInfo) {
        if (methodInfo.name) {
          var key = getMethodOverrideKey(methodInfo);
          if (key in Shumway.AVM2.Runtime.VM_METHOD_OVERRIDES) {
            Shumway.Debug.warning('Overriding Method: ' + key);
            return Shumway.AVM2.Runtime.VM_METHOD_OVERRIDES[key];
          }
        }
      }
      Runtime.checkMethodOverrides = checkMethodOverrides;
      function makeTrampoline(forward, parameterLength, description) {
        true;
        return function trampolineContext() {
          var target = null;
          var trampoline = function execute() {
            if (Shumway.AVM2.Runtime.traceExecution.value >= 3) {
              log('Trampolining');
            }
            Counter.count('Executing Trampoline');
            Shumway.AVM2.Runtime.traceCallExecution.value > 1 && callWriter.writeLn('Trampoline: ' + description);
            if (!target) {
              target = forward(trampoline);
              true;
            }
            return target.apply(this, arguments);
          };
          trampoline.trigger = function trigger() {
            Counter.count('Triggering Trampoline');
            if (!target) {
              target = forward(trampoline);
              true;
            }
          };
          trampoline.isTrampoline = true;
          trampoline.debugName = 'Trampoline #' + vmNextTrampolineId++;
          defineReadOnlyProperty(trampoline, Shumway.AVM2.Runtime.VM_LENGTH, parameterLength);
          return trampoline;
        }();
      }
      Runtime.makeTrampoline = makeTrampoline;
      function makeMemoizer(qn, target) {
        function memoizer() {
          Counter.count('Runtime: Memoizing');
          if (Shumway.AVM2.Runtime.traceExecution.value >= 3) {
            log('Memoizing: ' + qn);
          }
          Shumway.AVM2.Runtime.traceCallExecution.value > 1 && callWriter.writeLn('Memoizing: ' + qn);
          if (Shumway.AVM2.Runtime.isNativePrototype(this)) {
            Counter.count('Runtime: Method Closures');
            return bindSafely(target.value, this);
          }
          if (isTrampoline(target.value)) {
            target.value.trigger();
          }
          true;
          var mc = null;
          if (Shumway.AVM2.Runtime.isClass(this)) {
            Counter.count('Runtime: Static Method Closures');
            mc = bindSafely(target.value, this);
            defineReadOnlyProperty(this, qn, mc);
            return mc;
          }
          if (Object.prototype.hasOwnProperty.call(this, qn)) {
            var pd = Object.getOwnPropertyDescriptor(this, qn);
            if (pd.get) {
              Counter.count('Runtime: Method Closures');
              return bindSafely(target.value, this);
            }
            Counter.count('Runtime: Unpatched Memoizer');
            return this[qn];
          }
          mc = bindSafely(target.value, this);
          mc.methodInfo = target.value.methodInfo;
          defineReadOnlyProperty(mc, Multiname.getPublicQualifiedName('prototype'), null);
          defineReadOnlyProperty(this, qn, mc);
          return mc;
        }
        var m = memoizer;
        Counter.count('Runtime: Memoizers');
        m.isMemoizer = true;
        m.debugName = 'Memoizer #' + vmNextMemoizerId++;
        return m;
      }
      Runtime.makeMemoizer = makeMemoizer;
      function isTrampoline(fn) {
        true;
        return fn.isTrampoline;
      }
      Runtime.isTrampoline = isTrampoline;
      function isMemoizer(fn) {
        true;
        return fn.isMemoizer;
      }
      Runtime.isMemoizer = isMemoizer;
    }(AVM2.Runtime || (AVM2.Runtime = {})));
    var Runtime = AVM2.Runtime;
  }(Shumway.AVM2 || (Shumway.AVM2 = {})));
  var AVM2 = Shumway.AVM2;
}(Shumway || (Shumway = {})));
var __extends = this.__extends || function (d, b) {
    for (var p in b)
      if (b.hasOwnProperty(p))
        d[p] = b[p];
    function __() {
      this.constructor = d;
    }
    __.prototype = b.prototype;
    d.prototype = new __();
  };
var Shumway;
(function (Shumway) {
  (function (AVM2) {
    (function (Runtime) {
      var Multiname = Shumway.AVM2.ABC.Multiname;
      var Namespace = Shumway.AVM2.ABC.Namespace;
      var MethodInfo = Shumway.AVM2.ABC.MethodInfo;
      var ClassInfo = Shumway.AVM2.ABC.ClassInfo;
      var InstanceInfo = Shumway.AVM2.ABC.InstanceInfo;
      var ScriptInfo = Shumway.AVM2.ABC.ScriptInfo;
      var Trait = Shumway.AVM2.ABC.Trait;
      var IndentingWriter = Shumway.IndentingWriter;
      var hasOwnProperty = Shumway.ObjectUtilities.hasOwnProperty;
      var createMap = Shumway.ObjectUtilities.createMap;
      var cloneObject = Shumway.ObjectUtilities.cloneObject;
      var copyProperties = Shumway.ObjectUtilities.copyProperties;
      var createEmptyObject = Shumway.ObjectUtilities.createEmptyObject;
      var bindSafely = Shumway.FunctionUtilities.bindSafely;
      var defineNonEnumerableGetterOrSetter = Shumway.ObjectUtilities.defineNonEnumerableGetterOrSetter;
      var defineNonEnumerableProperty = Shumway.ObjectUtilities.defineNonEnumerableProperty;
      var defineReadOnlyProperty = Shumway.ObjectUtilities.defineReadOnlyProperty;
      var defineNonEnumerableGetter = Shumway.ObjectUtilities.defineNonEnumerableGetter;
      var makeForwardingGetter = Shumway.FunctionUtilities.makeForwardingGetter;
      var makeForwardingSetter = Shumway.FunctionUtilities.makeForwardingSetter;
      var Binding = function () {
          function Binding(trait) {
            this.trait = trait;
          }
          Binding.getKey = function (qn, trait) {
            var key = qn;
            if (trait.isGetter()) {
              key = Binding.GET_PREFIX + qn;
            } else if (trait.isSetter()) {
              key = Binding.SET_PREFIX + qn;
            }
            return key;
          };
          Binding.prototype.toString = function () {
            return String(this.trait);
          };
          Binding.SET_PREFIX = 'set ';
          Binding.GET_PREFIX = 'get ';
          Binding.KEY_PREFIX_LENGTH = 4;
          return Binding;
        }();
      Runtime.Binding = Binding;
      var SlotInfo = function () {
          function SlotInfo(name, isConst, type, trait) {
            this.name = name;
            this.isConst = isConst;
            this.type = type;
            this.trait = trait;
          }
          return SlotInfo;
        }();
      Runtime.SlotInfo = SlotInfo;
      var SlotInfoMap = function () {
          function SlotInfoMap() {
            this.byID = createMap();
            this.byQN = createMap();
          }
          return SlotInfoMap;
        }();
      Runtime.SlotInfoMap = SlotInfoMap;
      var Bindings = function () {
          function Bindings() {
            this.map = createMap();
            this.slots = [];
            this.nextSlotId = 1;
          }
          Bindings.prototype.assignNextSlot = function (trait) {
            true;
            true;
            if (!trait.slotId) {
              trait.slotId = this.nextSlotId++;
            } else {
              this.nextSlotId = trait.slotId + 1;
            }
            true;
            this.slots[trait.slotId] = trait;
          };
          Bindings.prototype.trace = function (writer) {
            writer.enter('Bindings');
            for (var key in this.map) {
              var binding = this.map[key];
              writer.writeLn(binding.trait.kindName() + ': ' + key + ' -> ' + binding);
            }
            writer.leaveAndEnter('Slots');
            writer.writeArray(this.slots);
            writer.outdent();
          };
          Bindings.prototype.applyTo = function (domain, object) {
            true;
            true;
            true;
            defineNonEnumerableProperty(object, Shumway.AVM2.Runtime.VM_SLOTS, new SlotInfoMap());
            defineNonEnumerableProperty(object, Shumway.AVM2.Runtime.VM_BINDINGS, []);
            defineNonEnumerableProperty(object, Shumway.AVM2.Runtime.VM_OPEN_METHODS, createMap());
            defineNonEnumerableProperty(object, 'bindings', this);
            defineNonEnumerableProperty(object, 'resolutionMap', []);
            traitsWriter && traitsWriter.greenLn('Applying Traits');
            for (var key in this.map) {
              var binding = this.map[key];
              var trait = binding.trait;
              var qn = Multiname.getQualifiedName(trait.name);
              if (trait.isSlot() || trait.isConst() || trait.isClass()) {
                var defaultValue = undefined;
                if (trait.isSlot() || trait.isConst()) {
                  if (trait.hasDefaultValue) {
                    defaultValue = trait.value;
                  } else if (trait.typeName) {
                    defaultValue = domain.findClassInfo(trait.typeName).defaultValue;
                  }
                }
                if (key !== qn) {
                  traitsWriter && traitsWriter.yellowLn('Binding Trait: ' + key + ' -> ' + qn);
                  defineNonEnumerableGetter(object, key, makeForwardingGetter(qn));
                  object.asBindings.pushUnique(key);
                } else {
                  traitsWriter && traitsWriter.greenLn('Applying Trait ' + trait.kindName() + ': ' + trait);
                  defineNonEnumerableProperty(object, qn, defaultValue);
                  object.asBindings.pushUnique(qn);
                  var slotInfo = new SlotInfo(qn, trait.isConst(), trait.typeName ? domain.getProperty(trait.typeName, false, false) : null, trait);
                  object.asSlots.byID[trait.slotId] = slotInfo;
                  object.asSlots.byQN[qn] = slotInfo;
                }
              } else if (trait.isMethod() || trait.isGetter() || trait.isSetter()) {
                if (trait.isGetter() || trait.isSetter()) {
                  key = key.substring(Binding.KEY_PREFIX_LENGTH);
                }
                if (key !== qn) {
                  traitsWriter && traitsWriter.yellowLn('Binding Trait: ' + key + ' -> ' + qn);
                } else {
                  traitsWriter && traitsWriter.greenLn('Applying Trait ' + trait.kindName() + ': ' + trait);
                }
                object.asBindings.pushUnique(key);
                if (this instanceof ScriptBindings) {
                  Shumway.AVM2.Runtime.applyNonMemoizedMethodTrait(key, trait, object, binding.scope, binding.natives);
                } else {
                  Shumway.AVM2.Runtime.applyMemoizedMethodTrait(key, trait, object, binding.scope, binding.natives);
                }
              }
            }
          };
          return Bindings;
        }();
      Runtime.Bindings = Bindings;
      var ActivationBindings = function (_super) {
          __extends(ActivationBindings, _super);
          function ActivationBindings(methodInfo) {
            _super.call(this);
            true;
            this.methodInfo = methodInfo;
            var traits = methodInfo.traits;
            for (var i = 0; i < traits.length; i++) {
              var trait = traits[i];
              true;
              var key = Multiname.getQualifiedName(trait.name);
              this.map[key] = new Binding(trait);
              this.assignNextSlot(trait);
            }
          }
          return ActivationBindings;
        }(Bindings);
      Runtime.ActivationBindings = ActivationBindings;
      var CatchBindings = function (_super) {
          __extends(CatchBindings, _super);
          function CatchBindings(scope, trait) {
            _super.call(this);
            var key = Multiname.getQualifiedName(trait.name);
            this.map[key] = new Binding(trait);
            true;
            this.assignNextSlot(trait);
          }
          return CatchBindings;
        }(Bindings);
      Runtime.CatchBindings = CatchBindings;
      var ScriptBindings = function (_super) {
          __extends(ScriptBindings, _super);
          function ScriptBindings(scriptInfo, scope) {
            _super.call(this);
            this.scope = scope;
            this.scriptInfo = scriptInfo;
            var traits = scriptInfo.traits;
            for (var i = 0; i < traits.length; i++) {
              var trait = traits[i];
              var name = Multiname.getQualifiedName(trait.name);
              var key = Binding.getKey(name, trait);
              var binding = this.map[key] = new Binding(trait);
              if (trait.isSlot() || trait.isConst() || trait.isClass()) {
                this.assignNextSlot(trait);
              }
              if (trait.isClass()) {
                if (trait.metadata && trait.metadata.native) {
                  trait.classInfo.native = trait.metadata.native;
                }
              }
              if (trait.isMethod() || trait.isGetter() || trait.isSetter()) {
                binding.scope = this.scope;
              }
            }
          }
          return ScriptBindings;
        }(Bindings);
      Runtime.ScriptBindings = ScriptBindings;
      var ClassBindings = function (_super) {
          __extends(ClassBindings, _super);
          function ClassBindings(classInfo, scope, natives) {
            _super.call(this);
            this.scope = scope;
            this.natives = natives;
            this.classInfo = classInfo;
            var traits = classInfo.traits;
            for (var i = 0; i < traits.length; i++) {
              var trait = traits[i];
              var name = Multiname.getQualifiedName(trait.name);
              var key = Binding.getKey(name, trait);
              var binding = this.map[key] = new Binding(trait);
              if (trait.isSlot() || trait.isConst()) {
                this.assignNextSlot(trait);
              }
              if (trait.isMethod() || trait.isGetter() || trait.isSetter()) {
                binding.scope = this.scope;
                binding.natives = this.natives;
              }
            }
          }
          return ClassBindings;
        }(Bindings);
      Runtime.ClassBindings = ClassBindings;
      var InstanceBindings = function (_super) {
          __extends(InstanceBindings, _super);
          function InstanceBindings(parent, instanceInfo, scope, natives) {
            _super.call(this);
            this.scope = scope;
            this.natives = natives;
            this.parent = parent;
            this.instanceInfo = instanceInfo;
            this.implementedInterfaces = parent ? cloneObject(parent.implementedInterfaces) : createEmptyObject();
            if (parent) {
              this.slots = parent.slots.slice();
              this.nextSlotId = parent.nextSlotId;
            }
            this.extend(parent);
          }
          InstanceBindings.prototype.extend = function (parent) {
            var ii = this.instanceInfo, ib;
            var map = this.map;
            var name, key, trait, binding, protectedName, protectedKey;
            if (parent) {
              for (key in parent.map) {
                binding = parent.map[key];
                trait = binding.trait;
                map[key] = binding;
                if (trait.isProtected()) {
                  protectedName = Multiname.getQualifiedName(new Multiname([
                    ii.protectedNs
                  ], trait.name.getName()));
                  protectedKey = Binding.getKey(protectedName, trait);
                  map[protectedKey] = binding;
                }
              }
            }
            function writeOrOverwriteBinding(object, key, binding) {
              var trait = binding.trait;
              var oldBinding = object[key];
              if (oldBinding) {
                var oldTrait = oldBinding.trait;
                true;
                true;
              } else {
                true;
              }
              object[key] = binding;
            }
            function overwriteProtectedBinding(object, key, binding) {
              if (key in object) {
                object[key] = binding;
              }
            }
            var traits = ii.traits;
            for (var i = 0; i < traits.length; i++) {
              trait = traits[i];
              name = Multiname.getQualifiedName(trait.name);
              key = Binding.getKey(name, trait);
              binding = new Binding(trait);
              writeOrOverwriteBinding(map, key, binding);
              if (trait.isProtected()) {
                ib = this.parent;
                while (ib) {
                  protectedName = Multiname.getQualifiedName(new Multiname([
                    ib.instanceInfo.protectedNs
                  ], trait.name.getName()));
                  protectedKey = Binding.getKey(protectedName, trait);
                  overwriteProtectedBinding(map, protectedKey, binding);
                  ib = ib.parent;
                }
              }
              if (trait.isSlot() || trait.isConst()) {
                this.assignNextSlot(trait);
              }
              if (trait.isMethod() || trait.isGetter() || trait.isSetter()) {
                binding.scope = this.scope;
                binding.natives = this.natives;
              }
            }
            var domain = ii.abc.applicationDomain;
            var interfaces = ii.interfaces;
            for (var i = 0; i < interfaces.length; i++) {
              var interface = domain.getProperty(interfaces[i], true, true);
              true;
              copyProperties(this.implementedInterfaces, interface.interfaceBindings.implementedInterfaces);
              this.implementedInterfaces[Multiname.getQualifiedName(interface.name)] = interface;
            }
            for (var interfaceName in this.implementedInterfaces) {
              var interface = this.implementedInterfaces[interfaceName];
              ib = interface.interfaceBindings;
              for (var interfaceKey in ib.map) {
                var interfaceBinding = ib.map[interfaceKey];
                if (ii.isInterface()) {
                  map[interfaceKey] = interfaceBinding;
                } else {
                  name = Multiname.getPublicQualifiedName(interfaceBinding.trait.name.getName());
                  key = Binding.getKey(name, interfaceBinding.trait);
                  map[interfaceKey] = map[key];
                }
              }
            }
          };
          InstanceBindings.prototype.toString = function () {
            return this.instanceInfo.toString();
          };
          return InstanceBindings;
        }(Bindings);
      Runtime.InstanceBindings = InstanceBindings;
      var traitsWriter = null;
    }(AVM2.Runtime || (AVM2.Runtime = {})));
    var Runtime = AVM2.Runtime;
  }(Shumway.AVM2 || (Shumway.AVM2 = {})));
  var AVM2 = Shumway.AVM2;
}(Shumway || (Shumway = {})));
var Binding = Shumway.AVM2.Runtime.Binding;
var Bindings = Shumway.AVM2.Runtime.Bindings;
var ActivationBindings = Shumway.AVM2.Runtime.ActivationBindings;
var CatchBindings = Shumway.AVM2.Runtime.CatchBindings;
var ScriptBindings = Shumway.AVM2.Runtime.ScriptBindings;
var ClassBindings = Shumway.AVM2.Runtime.ClassBindings;
var InstanceBindings = Shumway.AVM2.Runtime.InstanceBindings;
var Shumway;
(function (Shumway) {
  (function (AVM2) {
    (function (Runtime) {
      var Multiname = Shumway.AVM2.ABC.Multiname;
      var Namespace = Shumway.AVM2.ABC.Namespace;
      var MethodInfo = Shumway.AVM2.ABC.MethodInfo;
      var ClassInfo = Shumway.AVM2.ABC.ClassInfo;
      var InstanceInfo = Shumway.AVM2.ABC.InstanceInfo;
      var InstanceBindings = Shumway.AVM2.Runtime.InstanceBindings;
      var ClassBindings = Shumway.AVM2.Runtime.ClassBindings;
      var defineNonEnumerableGetterOrSetter = Shumway.ObjectUtilities.defineNonEnumerableGetterOrSetter;
      var defineNonEnumerableProperty = Shumway.ObjectUtilities.defineNonEnumerableProperty;
      var defineReadOnlyProperty = Shumway.ObjectUtilities.defineReadOnlyProperty;
      var defineNonEnumerableGetter = Shumway.ObjectUtilities.defineNonEnumerableGetter;
      var createEmptyObject = Shumway.ObjectUtilities.createEmptyObject;
      var toKeyValueArray = Shumway.ObjectUtilities.toKeyValueArray;
      var boxValue = Shumway.ObjectUtilities.boxValue;
      function makeCacheKey(namespaces, name, flags) {
        if (!namespaces) {
          return name;
        } else if (namespaces.length > 1) {
          return namespaces.runtimeId + '$' + name;
        } else {
          return namespaces[0].qualifiedName + '$' + name;
        }
      }
      var Scope = function () {
          function Scope(parent, object, isWith) {
            if (typeof isWith === 'undefined') {
              isWith = false;
            }
            this.parent = parent;
            this.object = boxValue(object);
            true;
            this.global = parent ? parent.global : this;
            this.isWith = isWith;
            this.cache = createEmptyObject();
          }
          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.findScopeProperty = function (namespaces, name, flags, domain, strict, scopeOnly) {
            Counter.count('findScopeProperty');
            var object;
            var key = makeCacheKey(namespaces, name, flags);
            if (!scopeOnly && (object = this.cache[key])) {
              return object;
            }
            if (this.object.asHasProperty(namespaces, name, flags, true)) {
              return this.isWith ? this.object : this.cache[key] = this.object;
            }
            if (this.parent) {
              return this.cache[key] = this.parent.findScopeProperty(namespaces, name, flags, domain, strict, scopeOnly);
            }
            if (scopeOnly)
              return null;
            if (object = domain.findDomainProperty(new Multiname(namespaces, name, flags), strict, true)) {
              return object;
            }
            if (strict) {
              Shumway.Debug.unexpected('Cannot find property ' + name);
            }
            return this.global.object;
          };
          return Scope;
        }();
      Runtime.Scope = Scope;
      function bindFreeMethodScope(methodInfo, scope) {
        var fn = methodInfo.freeMethod;
        if (methodInfo.lastBoundMethod && methodInfo.lastBoundMethod.scope === scope) {
          return methodInfo.lastBoundMethod.boundMethod;
        }
        true;
        var boundMethod;
        var asGlobal = scope.global.object;
        if (!methodInfo.hasOptional() && !methodInfo.needsArguments() && !methodInfo.needsRest()) {
          switch (methodInfo.parameters.length) {
          case 0:
            boundMethod = function () {
              return fn.call(this === jsGlobal ? asGlobal : this, scope);
            };
            break;
          case 1:
            boundMethod = function (x) {
              return fn.call(this === jsGlobal ? asGlobal : this, scope, x);
            };
            break;
          case 2:
            boundMethod = function (x, y) {
              return fn.call(this === jsGlobal ? asGlobal : this, scope, x, y);
            };
            break;
          case 3:
            boundMethod = function (x, y, z) {
              return fn.call(this === jsGlobal ? asGlobal : this, scope, x, y, z);
            };
            break;
          default:
            break;
          }
        }
        if (!boundMethod) {
          Counter.count('Bind Scope - Slow Path');
          boundMethod = function () {
            Array.prototype.unshift.call(arguments, scope);
            var global = this === jsGlobal ? scope.global.object : this;
            return fn.apply(global, arguments);
          };
        }
        boundMethod.methodInfo = methodInfo;
        boundMethod.instanceConstructor = boundMethod;
        methodInfo.lastBoundMethod = {
          scope: scope,
          boundMethod: boundMethod
        };
        return boundMethod;
      }
      Runtime.bindFreeMethodScope = bindFreeMethodScope;
    }(AVM2.Runtime || (AVM2.Runtime = {})));
    var Runtime = AVM2.Runtime;
  }(Shumway.AVM2 || (Shumway.AVM2 = {})));
  var AVM2 = Shumway.AVM2;
}(Shumway || (Shumway = {})));
var playerglobalLoadedPromise;
var playerglobal;
var Shumway;
(function (Shumway) {
  (function (AVM2) {
    (function (Runtime) {
      var AbcFile = Shumway.AVM2.ABC.AbcFile;
      var Multiname = Shumway.AVM2.ABC.Multiname;
      var Namespace = Shumway.AVM2.ABC.Namespace;
      var MethodInfo = Shumway.AVM2.ABC.MethodInfo;
      var ClassInfo = Shumway.AVM2.ABC.ClassInfo;
      var InstanceInfo = Shumway.AVM2.ABC.InstanceInfo;
      var ScriptInfo = Shumway.AVM2.ABC.ScriptInfo;
      var createEmptyObject = Shumway.ObjectUtilities.createEmptyObject;
      var IndentingWriter = Shumway.IndentingWriter;
      (function (EXECUTION_MODE) {
        EXECUTION_MODE[EXECUTION_MODE['INTERPRET'] = 1] = 'INTERPRET';
        EXECUTION_MODE[EXECUTION_MODE['COMPILE'] = 2] = 'COMPILE';
      }(Runtime.EXECUTION_MODE || (Runtime.EXECUTION_MODE = {})));
      var EXECUTION_MODE = Runtime.EXECUTION_MODE;
      function createNewCompartment() {
        return newGlobal('new-compartment');
      }
      function executeScript(script) {
        var abc = script.abc;
        true;
        var global = new Shumway.AVM2.Runtime.Global(script);
        if (abc.applicationDomain.allowNatives) {
          global[Multiname.getPublicQualifiedName('unsafeJSNative')] = getNative;
        }
        script.executing = true;
        var scope = new Shumway.AVM2.Runtime.Scope(null, script.global);
        createFunction(script.init, scope).call(script.global, false);
        script.executed = true;
      }
      Runtime.executeScript = executeScript;
      function ensureScriptIsExecuted(script, reason) {
        if (typeof reason === 'undefined') {
          reason = '';
        }
        if (!script.executed && !script.executing) {
          if (Shumway.AVM2.Runtime.traceExecution.value >= 2) {
            log('Executing Script For: ' + reason);
          }
          executeScript(script);
        }
      }
      Runtime.ensureScriptIsExecuted = ensureScriptIsExecuted;
      (function (Glue) {
        Glue[Glue['PUBLIC_PROPERTIES'] = 1] = 'PUBLIC_PROPERTIES';
        Glue[Glue['PUBLIC_METHODS'] = 2] = 'PUBLIC_METHODS';
        Glue[Glue['ALL'] = 1 | 2] = 'ALL';
      }(Runtime.Glue || (Runtime.Glue = {})));
      var Glue = Runtime.Glue;
      function grabAbc(abcName) {
        var entry = playerglobal.scripts[abcName];
        if (!entry) {
          return null;
        }
        var offset = entry.offset;
        var length = entry.length;
        return new AbcFile(new Uint8Array(playerglobal.abcs, offset, length), abcName);
      }
      function findDefiningAbc(mn) {
        if (!playerglobal) {
          return null;
        }
        for (var i = 0; i < mn.namespaces.length; i++) {
          var name = mn.namespaces[i].uri + ':' + mn.name;
          var abcName = playerglobal.map[name];
          if (abcName) {
            break;
          }
        }
        if (abcName) {
          return grabAbc(abcName);
        }
        return null;
      }
      function promiseFile(path, responseType) {
        return new Promise(function (resolve, reject) {
          var xhr = new XMLHttpRequest();
          xhr.open('GET', path);
          xhr.responseType = responseType;
          xhr.onload = function () {
            if (xhr.response) {
              resolve(xhr.response);
            } else {
              reject('Unable to load ' + path + ': ' + xhr.statusText);
            }
          };
          xhr.send();
        });
      }
      var AVM2 = function () {
          function AVM2(sysMode, appMode, loadAVM1) {
            this.systemDomain = new ApplicationDomain(this, null, sysMode, true);
            this.applicationDomain = new ApplicationDomain(this, this.systemDomain, appMode, false);
            this.findDefiningAbc = findDefiningAbc;
            this.loadAVM1 = loadAVM1;
            this.isAVM1Loaded = false;
            this.exception = {
              value: undefined
            };
            this.exceptions = [];
          }
          AVM2.initialize = function (sysMode, appMode, loadAVM1) {
            AVM2.instance = new AVM2(sysMode, appMode, loadAVM1);
          };
          AVM2.currentAbc = function () {
            var caller = arguments.callee;
            var maxDepth = 20;
            var abc = null;
            for (var i = 0; i < maxDepth && caller; i++) {
              var mi = caller.methodInfo;
              if (mi) {
                abc = mi.abc;
                break;
              }
              caller = caller.caller;
            }
            return abc;
          };
          AVM2.currentDomain = function () {
            var abc = AVM2.currentAbc();
            return abc.applicationDomain;
          };
          AVM2.isPlayerglobalLoaded = function () {
            return !(!playerglobal);
          };
          AVM2.loadPlayerglobal = function (abcsPath, catalogPath) {
            if (playerglobalLoadedPromise) {
              return Promise.reject('Playerglobal is already loaded');
            }
            playerglobalLoadedPromise = Promise.all([
              promiseFile(abcsPath, 'arraybuffer'),
              promiseFile(catalogPath, 'json')
            ]).then(function (result) {
              playerglobal = {
                abcs: result[0],
                map: Object.create(null),
                scripts: Object.create(null)
              };
              var catalog = result[1];
              for (var i = 0; i < catalog.length; i++) {
                var abc = catalog[i];
                playerglobal.scripts[abc.name] = abc;
                if (typeof abc.defs === 'string') {
                  playerglobal.map[abc.defs] = abc.name;
                } else {
                  for (var j = 0; j < abc.defs.length; j++) {
                    var def = abc.defs[j];
                    playerglobal.map[def] = abc.name;
                  }
                }
              }
            }, function (e) {
              console.error(e);
            });
            return playerglobalLoadedPromise;
          };
          AVM2.prototype.notifyConstruct = function (instanceConstructor, args) {
          };
          AVM2.getStackTrace = function () {
            Shumway.Debug.notImplemented('getStackTrace');
          };
          return AVM2;
        }();
      Runtime.AVM2 = AVM2;
      var ApplicationDomain = function () {
          function ApplicationDomain(vm, base, mode, allowNatives) {
            true;
            true;
            this.vm = vm;
            this.abcs = [];
            this.loadedAbcs = {};
            this.loadedClasses = [];
            this.classCache = createEmptyObject();
            this.scriptCache = createEmptyObject();
            this.classInfoCache = createEmptyObject();
            this.base = base;
            this.allowNatives = allowNatives;
            this.mode = mode;
            this.onMessage = new Callback();
            if (base) {
              this.system = base.system;
            } else {
              this.system = this;
            }
          }
          ApplicationDomain.passthroughCallable = function (f) {
            return {
              call: function ($this) {
                Array.prototype.shift.call(arguments);
                return f.apply($this, arguments);
              },
              apply: function ($this, args) {
                return f.apply($this, args);
              }
            };
          };
          ApplicationDomain.coerceCallable = function (type) {
            return {
              call: function ($this, value) {
                return Shumway.AVM2.Runtime.asCoerce(type, value);
              },
              apply: function ($this, args) {
                return Shumway.AVM2.Runtime.asCoerce(type, args[0]);
              }
            };
          };
          ApplicationDomain.constructingCallable = function (instanceConstructor) {
            return {
              call: function (self) {
                return new (Function.bind.apply(instanceConstructor, arguments))();
              },
              apply: function (self, args) {
                return new (Function.bind.apply(instanceConstructor, [
                  self
                ].concat(args)))();
              }
            };
          };
          ApplicationDomain.prototype.getType = function (multiname) {
            return this.getProperty(multiname, true, true);
          };
          ApplicationDomain.prototype.getProperty = function (multiname, strict, execute) {
            var resolved = this.findDefiningScript(multiname, execute);
            if (resolved) {
              if (!resolved.script.executing) {
                return undefined;
              }
              return resolved.script.global[Multiname.getQualifiedName(resolved.trait.name)];
            }
            if (strict) {
              return Shumway.Debug.unexpected('Cannot find property ' + multiname);
            }
            return undefined;
          };
          ApplicationDomain.prototype.getClass = function (simpleName) {
            var cache = this.classCache;
            var c = cache[simpleName];
            if (!c) {
              c = cache[simpleName] = this.getProperty(Multiname.fromSimpleName(simpleName), true, true);
            }
            true;
            return c;
          };
          ApplicationDomain.prototype.findClass = function (simpleName) {
            if (simpleName in this.classCache) {
              return true;
            }
            return this.findDomainProperty(Multiname.fromSimpleName(simpleName), false, true);
          };
          ApplicationDomain.prototype.findDomainProperty = function (multiname, strict, execute) {
            if (Shumway.AVM2.Runtime.traceDomain.value) {
              log('ApplicationDomain.findDomainProperty: ' + multiname);
            }
            var resolved = this.findDefiningScript(multiname, execute);
            if (resolved) {
              return resolved.script.global;
            }
            if (strict) {
              return Shumway.Debug.unexpected('Cannot find property ' + multiname);
            } else {
              return undefined;
            }
            return undefined;
          };
          ApplicationDomain.prototype.findClassInfo = function (mn) {
            var originalQn;
            if (Multiname.isQName(mn)) {
              originalQn = Multiname.getQualifiedName(mn);
              var ci = this.classInfoCache[originalQn];
              if (ci) {
                return ci;
              }
            } else {
              var ci = this.classInfoCache[mn.runtimeId];
              if (ci) {
                return ci;
              }
            }
            if (this.base) {
              ci = this.base.findClassInfo(mn);
              if (ci) {
                return ci;
              }
            }
            var abcs = this.abcs;
            for (var i = 0; i < abcs.length; i++) {
              var abc = abcs[i];
              var scripts = abc.scripts;
              for (var j = 0; j < scripts.length; j++) {
                var script = scripts[j];
                var traits = script.traits;
                for (var k = 0; k < traits.length; k++) {
                  var trait = traits[k];
                  if (trait.isClass()) {
                    var traitName = Multiname.getQualifiedName(trait.name);
                    if (originalQn) {
                      if (traitName === originalQn) {
                        return this.classInfoCache[originalQn] = trait.classInfo;
                      }
                    } else {
                      for (var m = 0, n = mn.namespaces.length; m < n; m++) {
                        var qn = mn.getQName(m);
                        if (traitName === Multiname.getQualifiedName(qn)) {
                          return this.classInfoCache[qn] = trait.classInfo;
                        }
                      }
                    }
                  }
                }
              }
            }
            if (!this.base && this.vm.findDefiningAbc) {
              var abc = this.vm.findDefiningAbc(mn);
              if (abc !== null && !this.loadedAbcs[abc.name]) {
                this.loadedAbcs[abc.name] = true;
                this.loadAbc(abc);
                return this.findClassInfo(mn);
              }
            }
            return undefined;
          };
          ApplicationDomain.prototype.installNative = function (name, func) {
            natives[name] = function () {
              return func;
            };
          };
          ApplicationDomain.prototype.findDefiningScript = function (mn, execute) {
            var resolved = this.scriptCache[mn.runtimeId];
            if (resolved && (resolved.script.executed || !execute)) {
              return resolved;
            }
            if (this.base) {
              resolved = this.base.findDefiningScript(mn, execute);
              if (resolved) {
                return resolved;
              }
            }
            Counter.count('ApplicationDomain: findDefiningScript');
            var abcs = this.abcs;
            for (var i = 0; i < abcs.length; i++) {
              var abc = abcs[i];
              var scripts = abc.scripts;
              for (var j = 0; j < scripts.length; j++) {
                var script = scripts[j];
                var traits = script.traits;
                if (mn instanceof Multiname) {
                  for (var k = 0; k < traits.length; k++) {
                    var trait = traits[k];
                    if (mn.hasQName(trait.name)) {
                      if (execute) {
                        ensureScriptIsExecuted(script, String(trait.name));
                      }
                      return this.scriptCache[mn.runtimeId] = {
                        script: script,
                        trait: trait
                      };
                    }
                  }
                } else {
                  Shumway.Debug.unexpected();
                }
              }
            }
            if (!this.base && this.vm.findDefiningAbc) {
              var abc = this.vm.findDefiningAbc(mn);
              if (abc !== null && !this.loadedAbcs[abc.name]) {
                this.loadedAbcs[abc.name] = true;
                this.loadAbc(abc);
                return this.findDefiningScript(mn, execute);
              }
            }
            return undefined;
          };
          ApplicationDomain.prototype.compileAbc = function (abc, writer) {
            compileAbc(abc, writer);
          };
          ApplicationDomain.prototype.executeAbc = function (abc) {
            this.loadAbc(abc);
            executeScript(abc.lastScript);
          };
          ApplicationDomain.prototype.loadAbc = function (abc) {
            if (Shumway.AVM2.Runtime.traceExecution.value) {
              log('Loading: ' + abc.name);
            }
            abc.applicationDomain = this;
            GlobalMultinameResolver.loadAbc(abc);
            this.abcs.push(abc);
            if (!this.base) {
              Type.initializeTypes(this);
            }
          };
          ApplicationDomain.prototype.broadcastMessage = function (type, message, origin) {
            if (debug) {
              Timer.start('broadcast: ' + type);
            }
            try {
              this.onMessage.notify1(type, {
                data: message,
                origin: origin,
                source: this
              });
            } catch (e) {
              avm2.exceptions.push({
                source: type,
                message: e.message,
                stack: e.stack
              });
              throw e;
            }
            if (debug) {
              Timer.stop();
            }
          };
          ApplicationDomain.prototype.traceLoadedClasses = function (lastOnly) {
            var writer = new IndentingWriter();
            lastOnly || writer.enter('Loaded Classes And Interfaces');
            var classes = lastOnly ? [
                this.loadedClasses.last()
              ] : this.loadedClasses;
            classes.forEach(function (cls) {
              if (cls !== Shumway.AVM2.Runtime.Class) {
                cls.trace(writer);
              }
            });
            lastOnly || writer.leave('');
          };
          return ApplicationDomain;
        }();
      Runtime.ApplicationDomain = ApplicationDomain;
      var SecurityDomain = function () {
          function SecurityDomain() {
            this.compartment = createNewCompartment();
            this.compartment.homePath = homePath;
            this.compartment.release = true;
            this.compartment.eval(snarf('compartment.js'));
          }
          SecurityDomain.prototype.initializeShell = function (sysMode, appMode) {
            var compartment = this.compartment;
            compartment.AVM2.initialize(sysMode, appMode);
            compartment.AVM2.instance.systemDomain.executeAbc(compartment.grabAbc(homePath + 'src/avm2/generated/builtin/builtin.abc'));
            compartment.AVM2.instance.systemDomain.executeAbc(compartment.grabAbc(homePath + 'src/avm2/generated/shell/shell.abc'));
            this.systemDomain = compartment.AVM2.instance.systemDomain;
            this.applicationDomain = compartment.AVM2.instance.applicationDomain;
          };
          return SecurityDomain;
        }();
      Runtime.SecurityDomain = SecurityDomain;
    }(AVM2.Runtime || (AVM2.Runtime = {})));
    var Runtime = AVM2.Runtime;
  }(Shumway.AVM2 || (Shumway.AVM2 = {})));
  var AVM2 = Shumway.AVM2;
}(Shumway || (Shumway = {})));
var Glue = Shumway.AVM2.Runtime.Glue;
var ApplicationDomain = Shumway.AVM2.Runtime.ApplicationDomain;
var AVM2 = Shumway.AVM2.Runtime.AVM2;
var EXECUTION_MODE = Shumway.AVM2.Runtime.EXECUTION_MODE;
var ApplicationDomain = Shumway.AVM2.Runtime.ApplicationDomain;
var AVM2 = Shumway.AVM2.Runtime.AVM2;
var EXECUTION_MODE = Shumway.AVM2.Runtime.EXECUTION_MODE;
var Shumway;
(function (Shumway) {
  (function (AVM2) {
    (function (Runtime) {
      var Multiname = Shumway.AVM2.ABC.Multiname;
      var Namespace = Shumway.AVM2.ABC.Namespace;
      var ClassInfo = Shumway.AVM2.ABC.ClassInfo;
      var InstanceInfo = Shumway.AVM2.ABC.InstanceInfo;
      var InstanceBindings = Shumway.AVM2.Runtime.InstanceBindings;
      var ClassBindings = Shumway.AVM2.Runtime.ClassBindings;
      var defineNonEnumerableGetterOrSetter = Shumway.ObjectUtilities.defineNonEnumerableGetterOrSetter;
      var defineNonEnumerableProperty = Shumway.ObjectUtilities.defineNonEnumerableProperty;
      var defineReadOnlyProperty = Shumway.ObjectUtilities.defineReadOnlyProperty;
      var defineNonEnumerableGetter = Shumway.ObjectUtilities.defineNonEnumerableGetter;
      var createEmptyObject = Shumway.ObjectUtilities.createEmptyObject;
      var toKeyValueArray = Shumway.ObjectUtilities.toKeyValueArray;
      var Interface = function () {
          function Interface(classInfo) {
            var ii = classInfo.instanceInfo;
            true;
            this.name = ii.name;
            this.classInfo = classInfo;
          }
          Interface.createInterface = function (classInfo) {
            var ii = classInfo.instanceInfo;
            true;
            if (Shumway.AVM2.Runtime.traceExecution.value) {
              var str = 'Creating Interface ' + ii.name;
              if (ii.interfaces.length) {
                str += ' implements ' + ii.interfaces.map(function (name) {
                  return name.getName();
                }).join(', ');
              }
              log(str);
            }
            var cls = new Interface(classInfo);
            cls.interfaceBindings = new InstanceBindings(null, ii, null, null);
            return cls;
          };
          Interface.prototype.toString = function () {
            return '[interface ' + this.name + ']';
          };
          Interface.prototype.isInstance = function (value) {
            if (value === null || typeof value !== 'object') {
              return false;
            }
            true;
            var qualifiedName = Multiname.getQualifiedName(this.name);
            return value.class.implementedInterfaces[qualifiedName] !== undefined;
          };
          Interface.prototype.trace = function (writer) {
            writer.enter('interface ' + this.name.getName());
            writer.enter('interfaceBindings: ');
            this.interfaceBindings.trace(writer);
            writer.outdent();
            writer.outdent();
            writer.leave('}');
          };
          Interface.prototype.call = function (self, x) {
            return x;
          };
          Interface.prototype.apply = function (self, args) {
            return args[0];
          };
          return Interface;
        }();
      Runtime.Interface = Interface;
      function setDefaultProperties(cls) {
        defineNonEnumerableProperty(cls.dynamicPrototype, Multiname.getPublicQualifiedName('constructor'), cls);
        defineReadOnlyProperty(cls.traitsPrototype, 'class', cls);
        defineReadOnlyProperty(cls.instanceConstructor, 'class', cls);
      }
      Runtime.setDefaultProperties = setDefaultProperties;
      var Class = function () {
          function Class(name, instanceConstructor, callable) {
            this.debugName = name;
            if (instanceConstructor) {
              true;
              this.instanceConstructor = instanceConstructor;
              this.instanceConstructorNoInitialize = instanceConstructor;
              this.hasInitialize = 0;
              this.instanceConstructor.class = this;
            }
            if (!callable) {
              callable = Shumway.AVM2.Runtime.ApplicationDomain.coerceCallable(this);
            } else if (callable === Shumway.AVM2.Runtime.ApplicationDomain.coerceCallable) {
              callable = Shumway.AVM2.Runtime.ApplicationDomain.coerceCallable(this);
            }
            defineNonEnumerableProperty(this, 'call', callable.call);
            defineNonEnumerableProperty(this, 'apply', callable.apply);
          }
          Class.createClass = function (classInfo, baseClass, scope) {
            var ci = classInfo;
            var ii = ci.instanceInfo;
            var domain = ci.abc.applicationDomain;
            var className = Multiname.getName(ii.name);
            var isNativeClass = ci.native;
            if (isNativeClass) {
              var buildClass = getNative(ci.native.cls);
              if (!buildClass) {
                Shumway.Debug.unexpected('No native for ' + ci.native.cls);
              }
              if (!baseClass) {
                scope = new Scope(scope, Class);
              }
            }
            var classScope = new Scope(scope, null);
            var instanceConstructor = createFunction(ii.init, classScope, false);
            var cls;
            if (isNativeClass) {
              cls = buildClass(domain, classScope, instanceConstructor, baseClass);
            } else {
              cls = new Class(className, instanceConstructor);
            }
            cls.className = className;
            cls.classInfo = classInfo;
            cls.scope = classScope;
            classScope.object = cls;
            var classNatives;
            var instanceNatives;
            if (isNativeClass) {
              if (cls.native) {
                classNatives = cls.native.static;
                instanceNatives = cls.native.instance;
              }
            } else {
              cls.extend(baseClass);
            }
            cls.classBindings = new ClassBindings(classInfo, classScope, classNatives);
            cls.classBindings.applyTo(domain, cls);
            defineReadOnlyProperty(cls, Shumway.AVM2.Runtime.VM_IS_CLASS, true);
            cls.instanceBindings = new InstanceBindings(baseClass ? baseClass.instanceBindings : null, ii, classScope, instanceNatives);
            if (cls.instanceConstructor) {
              cls.instanceBindings.applyTo(domain, cls.traitsPrototype);
            }
            cls.implementedInterfaces = cls.instanceBindings.implementedInterfaces;
            return cls;
          };
          Class.prototype.setSymbol = function (props) {
            this.instanceConstructor.prototype.symbol = props;
          };
          Class.prototype.getSymbol = function () {
            return this.instanceConstructor.prototype.symbol;
          };
          Class.prototype.initializeInstance = function (obj) {
            var c = this;
            var initializes = [];
            while (c) {
              if (c.hasInitialize & Class.OWN_INITIALIZE) {
                initializes.push(c.instanceConstructor.prototype.initialize);
              }
              c = c.baseClass;
            }
            var s;
            while (s = initializes.pop()) {
              s.call(obj);
            }
            Counter.count('Initialize Instance ' + obj.class);
          };
          Class.prototype.createInstance = function (args) {
            var o = Object.create(this.instanceConstructor.prototype);
            this.instanceConstructor.apply(o, args);
            return o;
          };
          Class.prototype.createAsSymbol = function (props) {
            var o = Object.create(this.instanceConstructor.prototype);
            if (o.symbol) {
              var symbol = Object.create(o.symbol);
              for (var prop in props) {
                symbol[prop] = props[prop];
              }
              o.symbol = symbol;
            } else {
              o.symbol = props;
            }
            return o;
          };
          Class.prototype.extendNative = function (baseClass, native) {
            this.baseClass = baseClass;
            this.dynamicPrototype = Object.getPrototypeOf(native.prototype);
            this.instanceConstructor.prototype = this.traitsPrototype = native.prototype;
            setDefaultProperties(this);
          };
          Class.prototype.extendWrapper = function (baseClass, wrapper) {
            true;
            this.baseClass = baseClass;
            this.dynamicPrototype = Object.create(baseClass.dynamicPrototype);
            var traitsPrototype = Object.create(this.dynamicPrototype, Shumway.ObjectUtilities.getOwnPropertyDescriptors(wrapper.prototype));
            this.instanceConstructor.prototype = this.traitsPrototype = traitsPrototype;
            setDefaultProperties(this);
          };
          Class.prototype.extendBuiltin = function (baseClass) {
            true;
            this.baseClass = baseClass;
            this.dynamicPrototype = this.traitsPrototype = this.instanceConstructor.prototype;
            setDefaultProperties(this);
          };
          Class.prototype.extend = function (baseClass) {
            true;
            this.baseClass = baseClass;
            this.dynamicPrototype = Object.create(baseClass.dynamicPrototype);
            if (baseClass.hasInitialize) {
              var instanceConstructorNoInitialize = this.instanceConstructor;
              var self = this;
              this.instanceConstructor = function () {
                self.initializeInstance(this);
                instanceConstructorNoInitialize.apply(this, arguments);
              };
              defineReadOnlyProperty(this.instanceConstructor, 'class', instanceConstructorNoInitialize.class);
              this.hasInitialize |= Class.SUPER_INITIALIZE;
            }
            this.instanceConstructor.prototype = this.traitsPrototype = Object.create(this.dynamicPrototype);
            setDefaultProperties(this);
          };
          Class.prototype.setDefaultProperties = function () {
            setDefaultProperties(this);
          };
          Class.prototype.link = function (definition) {
            true;
            true;
            if (definition.initialize) {
              if (!this.hasInitialize) {
                var instanceConstructorNoInitialize = this.instanceConstructor;
                var self = this;
                this.instanceConstructor = function () {
                  self.initializeInstance(this);
                  instanceConstructorNoInitialize.apply(this, arguments);
                };
                defineReadOnlyProperty(this.instanceConstructor, 'class', instanceConstructorNoInitialize.class);
                this.instanceConstructor.prototype = instanceConstructorNoInitialize.prototype;
              }
              this.hasInitialize |= Class.OWN_INITIALIZE;
            }
            var dynamicPrototype = this.dynamicPrototype;
            var keys = Object.keys(definition);
            for (var i = 0; i < keys.length; i++) {
              var propertyName = keys[i];
              Object.defineProperty(dynamicPrototype, propertyName, Object.getOwnPropertyDescriptor(definition, propertyName));
            }
            function glueProperties(obj, properties) {
              var keys = Object.keys(properties);
              for (var i = 0; i < keys.length; i++) {
                var propertyName = keys[i];
                var propertyGlue = properties[propertyName];
                var propertySimpleName;
                var glueOpenMethod = false;
                if (propertyGlue.indexOf('open ') >= 0) {
                  propertySimpleName = propertyGlue.substring(5);
                  glueOpenMethod = true;
                } else {
                  propertySimpleName = propertyGlue;
                }
                true;
                var qn = Multiname.getQualifiedName(Multiname.fromSimpleName(propertySimpleName));
                if (glueOpenMethod) {
                  qn = Shumway.AVM2.Runtime.VM_OPEN_METHOD_PREFIX + qn;
                }
                true;
                var descriptor = Object.getOwnPropertyDescriptor(obj, qn);
                if (descriptor && descriptor.get) {
                  Object.defineProperty(obj, propertyName, descriptor);
                } else {
                  Object.defineProperty(obj, propertyName, {
                    get: new Function('', 'return this.' + qn),
                    set: new Function('v', 'this.' + qn + ' = v')
                  });
                }
              }
            }
            function generatePropertiesFromTraits(traits) {
              var properties = createEmptyObject();
              traits.forEach(function (trait) {
                var ns = trait.name.getNamespace();
                if (!ns.isPublic()) {
                  return;
                }
                properties[trait.name.getName()] = (trait.isMethod() ? 'open ' : '') + 'public ' + trait.name.getName();
              });
              return properties;
            }
            var glue = definition.__glue__;
            if (!glue) {
              return;
            }
            if (glue.script) {
              if (glue.script.instance) {
                if (Shumway.isNumber(glue.script.instance)) {
                  true;
                  glueProperties(dynamicPrototype, generatePropertiesFromTraits(this.classInfo.instanceInfo.traits));
                } else {
                  glueProperties(dynamicPrototype, glue.script.instance);
                }
              }
              if (glue.script.static) {
                if (Shumway.isNumber(glue.script.static)) {
                  true;
                  glueProperties(this, generatePropertiesFromTraits(this.classInfo.traits));
                } else {
                  glueProperties(this, glue.script.static);
                }
              }
            }
          };
          Class.prototype.linkNatives = function (definition) {
            var glue = definition.__glue__;
            this.native = glue.native;
          };
          Class.prototype.verify = function () {
            var instanceConstructor = this.instanceConstructor;
            var tP = this.traitsPrototype;
            var dP = this.dynamicPrototype;
            true;
            true;
            true;
            true;
            if (tP !== Object.prototype) {
            }
            true;
          };
          Class.prototype.coerce = function (value) {
            return value;
          };
          Class.prototype.isInstanceOf = function (value) {
            return this.isInstance(value);
          };
          Class.prototype.isInstance = function (value) {
            if (value === null || typeof value !== 'object') {
              return false;
            }
            return this.dynamicPrototype.isPrototypeOf(value);
          };
          Class.prototype.trace = function (writer) {
            var description = this.debugName + (this.baseClass ? ' extends ' + this.baseClass.debugName : '');
            writer.enter('class ' + description + ' {');
            writer.writeLn('scope: ' + this.scope);
            writer.writeLn('baseClass: ' + this.baseClass);
            writer.writeLn('classInfo: ' + this.classInfo);
            writer.writeLn('dynamicPrototype: ' + this.dynamicPrototype);
            writer.writeLn('traitsPrototype: ' + this.traitsPrototype);
            writer.writeLn('dynamicPrototype === traitsPrototype: ' + (this.dynamicPrototype === this.traitsPrototype));
            writer.writeLn('instanceConstructor: ' + this.instanceConstructor);
            writer.writeLn('instanceConstructorNoInitialize: ' + this.instanceConstructorNoInitialize);
            writer.writeLn('instanceConstructor === instanceConstructorNoInitialize: ' + (this.instanceConstructor === this.instanceConstructorNoInitialize));
            var traitsPrototype = this.traitsPrototype;
            writer.enter('traitsPrototype: ');
            if (traitsPrototype) {
              writer.enter('VM_SLOTS: ');
              writer.writeArray(traitsPrototype.asSlots.byID.map(function (slot) {
                return slot.trait;
              }));
              writer.outdent();
              writer.enter('VM_BINDINGS: ');
              writer.writeArray(traitsPrototype.asBindings.map(function (binding) {
                var pd = Object.getOwnPropertyDescriptor(traitsPrototype, binding);
                var str = binding;
                if (pd.get || pd.set) {
                  if (pd.get) {
                    str += ' getter: ' + debugName(pd.get);
                  }
                  if (pd.set) {
                    str += ' setter: ' + debugName(pd.set);
                  }
                } else {
                  str += ' value: ' + debugName(pd.value);
                }
                return str;
              }));
              writer.outdent();
              writer.enter('VM_OPEN_METHODS: ');
              writer.writeArray(toKeyValueArray(traitsPrototype.asOpenMethods).map(function (pair) {
                return pair[0] + ': ' + debugName(pair[1]);
              }));
              writer.outdent();
            }
            writer.enter('classBindings: ');
            this.classBindings.trace(writer);
            writer.outdent();
            writer.enter('instanceBindings: ');
            this.instanceBindings.trace(writer);
            writer.outdent();
            writer.outdent();
            writer.writeLn('call: ' + this.call);
            writer.writeLn('apply: ' + this.apply);
            writer.leave('}');
          };
          Class.prototype.toString = function () {
            return '[class ' + this.classInfo.instanceInfo.name.name + ']';
          };
          Class.OWN_INITIALIZE = 1;
          Class.SUPER_INITIALIZE = 2;
          return Class;
        }();
      Runtime.Class = Class;
      var callable = Shumway.AVM2.Runtime.ApplicationDomain.coerceCallable(Class);
      defineNonEnumerableProperty(Class, 'call', callable.call);
      defineNonEnumerableProperty(Class, 'apply', callable.apply);
      Class.instanceConstructor = Class;
      Class.toString = Class.prototype.toString;
      Class.native = {
        instance: {
          prototype: {
            get: function () {
              return this.dynamicPrototype;
            }
          }
        }
      };
    }(AVM2.Runtime || (AVM2.Runtime = {})));
    var Runtime = AVM2.Runtime;
  }(Shumway.AVM2 || (Shumway.AVM2 = {})));
  var AVM2 = Shumway.AVM2;
}(Shumway || (Shumway = {})));
var Interface = Shumway.AVM2.Runtime.Interface;
var Class = Shumway.AVM2.Runtime.Class;
var Binding = Shumway.AVM2.Runtime.Binding;
var Bindings = Shumway.AVM2.Runtime.Bindings;
var ActivationBindings = Shumway.AVM2.Runtime.ActivationBindings;
var CatchBindings = Shumway.AVM2.Runtime.CatchBindings;
var ScriptBindings = Shumway.AVM2.Runtime.ScriptBindings;
var ClassBindings = Shumway.AVM2.Runtime.ClassBindings;
var InstanceBindings = Shumway.AVM2.Runtime.InstanceBindings;
var Interface = Shumway.AVM2.Runtime.Interface;
var Class = Shumway.AVM2.Runtime.Class;
var XRegExp = function (undefined) {
    var REGEX_DATA = 'xregexp', self, features = {
        astral: false,
        natives: false
      }, nativ = {
        exec: RegExp.prototype.exec,
        test: RegExp.prototype.test,
        match: String.prototype.match,
        replace: String.prototype.replace,
        split: String.prototype.split
      }, fixed = {}, cache = {}, patternCache = {}, tokens = [], defaultScope = 'default', classScope = 'class', nativeTokens = {
        'default': /\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9]\d*|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S])|\(\?[:=!]|[?*+]\?|{\d+(?:,\d*)?}\??|[\s\S]/,
        'class': /\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S])|[\s\S]/
      }, replacementToken = /\$(?:{([\w$]+)}|([\d$&`']))/g, correctExecNpcg = nativ.exec.call(/()??/, '')[1] === undefined, hasNativeY = RegExp.prototype.sticky !== undefined, registeredFlags = {
        g: true,
        i: true,
        m: true,
        y: hasNativeY
      }, toString = {}.toString, add;
    function augment(regex, captureNames, addProto) {
      var p;
      if (addProto) {
        if (regex.__proto__) {
          regex.__proto__ = self.prototype;
        } else {
          for (p in self.prototype) {
            regex[p] = self.prototype[p];
          }
        }
      }
      regex[REGEX_DATA] = {
        captureNames: captureNames
      };
      return regex;
    }
    function clipDuplicates(str) {
      return nativ.replace.call(str, /([\s\S])(?=[\s\S]*\1)/g, '');
    }
    function copy(regex, options) {
      if (!self.isRegExp(regex)) {
        throw new TypeError('Type RegExp expected');
      }
      var flags = nativ.exec.call(/\/([a-z]*)$/i, String(regex))[1];
      options = options || {};
      if (options.add) {
        flags = clipDuplicates(flags + options.add);
      }
      if (options.remove) {
        flags = nativ.replace.call(flags, new RegExp('[' + options.remove + ']+', 'g'), '');
      }
      regex = augment(new RegExp(regex.source, flags), hasNamedCapture(regex) ? regex[REGEX_DATA].captureNames.slice(0) : null, options.addProto);
      return regex;
    }
    function getBaseProps() {
      return {
        captureNames: null
      };
    }
    function hasNamedCapture(regex) {
      return !(!(regex[REGEX_DATA] && regex[REGEX_DATA].captureNames));
    }
    function indexOf(array, value) {
      if (Array.prototype.indexOf) {
        return array.indexOf(value);
      }
      var len = array.length, i;
      for (i = 0; i < len; ++i) {
        if (array[i] === value) {
          return i;
        }
      }
      return -1;
    }
    function isType(value, type) {
      return toString.call(value) === '[object ' + type + ']';
    }
    function isQuantifierNext(pattern, pos, flags) {
      return nativ.test.call(flags.indexOf('x') > -1 ? /^(?:\s+|#.*|\(\?#[^)]*\))*(?:[?*+]|{\d+(?:,\d*)?})/ : /^(?:\(\?#[^)]*\))*(?:[?*+]|{\d+(?:,\d*)?})/, pattern.slice(pos));
    }
    function prepareFlags(pattern, flags) {
      var i;
      if (clipDuplicates(flags) !== flags) {
        throw new SyntaxError('Invalid duplicate regex flag ' + flags);
      }
      pattern = nativ.replace.call(pattern, /^\(\?([\w$]+)\)/, function ($0, $1) {
        if (nativ.test.call(/[gy]/, $1)) {
          throw new SyntaxError('Cannot use flag g or y in mode modifier ' + $0);
        }
        flags = clipDuplicates(flags + $1);
        return '';
      });
      for (i = 0; i < flags.length; ++i) {
        if (!registeredFlags[flags.charAt(i)]) {
          throw new SyntaxError('Unknown regex flag ' + flags.charAt(i));
        }
      }
      return {
        pattern: pattern,
        flags: flags
      };
    }
    function prepareOptions(value) {
      value = value || {};
      if (isType(value, 'String')) {
        value = self.forEach(value, /[^\s,]+/, function (match) {
          this[match] = true;
        }, {});
      }
      return value;
    }
    function registerFlag(flag) {
      if (!/^[\w$]$/.test(flag)) {
        throw new Error('Flag must be a single character A-Za-z0-9_$');
      }
      registeredFlags[flag] = true;
    }
    function runTokens(pattern, flags, pos, scope, context) {
      var i = tokens.length, result = null, match, t;
      while (i--) {
        t = tokens[i];
        if ((t.scope === scope || t.scope === 'all') && (!t.flag || flags.indexOf(t.flag) > -1)) {
          match = self.exec(pattern, t.regex, pos, 'sticky');
          if (match) {
            result = {
              matchLength: match[0].length,
              output: t.handler.call(context, match, scope, flags),
              reparse: t.reparse
            };
            break;
          }
        }
      }
      return result;
    }
    function setAstral(on) {
      self.cache.flush('patterns');
      features.astral = on;
    }
    function setNatives(on) {
      RegExp.prototype.exec = (on ? fixed : nativ).exec;
      RegExp.prototype.test = (on ? fixed : nativ).test;
      String.prototype.match = (on ? fixed : nativ).match;
      String.prototype.replace = (on ? fixed : nativ).replace;
      String.prototype.split = (on ? fixed : nativ).split;
      features.natives = on;
    }
    function toObject(value) {
      if (value == null) {
        throw new TypeError('Cannot convert null or undefined to object');
      }
      return value;
    }
    self = function (pattern, flags) {
      var context = {
          hasNamedCapture: false,
          captureNames: []
        }, scope = defaultScope, output = '', pos = 0, result, token, key;
      if (self.isRegExp(pattern)) {
        if (flags !== undefined) {
          throw new TypeError('Cannot supply flags when copying a RegExp');
        }
        return copy(pattern, {
          addProto: true
        });
      }
      pattern = pattern === undefined ? '' : String(pattern);
      flags = flags === undefined ? '' : String(flags);
      key = pattern + '***' + flags;
      if (!patternCache[key]) {
        result = prepareFlags(pattern, flags);
        pattern = result.pattern;
        flags = result.flags;
        while (pos < pattern.length) {
          do {
            result = runTokens(pattern, flags, pos, scope, context);
            if (result && result.reparse) {
              pattern = pattern.slice(0, pos) + result.output + pattern.slice(pos + result.matchLength);
            }
          } while (result && result.reparse);
          if (result) {
            output += result.output;
            pos += result.matchLength || 1;
          } else {
            token = self.exec(pattern, nativeTokens[scope], pos, 'sticky')[0];
            output += token;
            pos += token.length;
            if (token === '[' && scope === defaultScope) {
              scope = classScope;
            } else if (token === ']' && scope === classScope) {
              scope = defaultScope;
            }
          }
        }
        patternCache[key] = {
          pattern: nativ.replace.call(output, /\(\?:\)(?=\(\?:\))|^\(\?:\)|\(\?:\)$/g, ''),
          flags: nativ.replace.call(flags, /[^gimy]+/g, ''),
          captures: context.hasNamedCapture ? context.captureNames : null
        };
      }
      key = patternCache[key];
      return augment(new RegExp(key.pattern, key.flags), key.captures, true);
    };
    self.prototype = new RegExp();
    self.version = '3.0.0-pre';
    self.addToken = function (regex, handler, options) {
      options = options || {};
      var optionalFlags = options.optionalFlags, i;
      if (options.flag) {
        registerFlag(options.flag);
      }
      if (optionalFlags) {
        optionalFlags = nativ.split.call(optionalFlags, '');
        for (i = 0; i < optionalFlags.length; ++i) {
          registerFlag(optionalFlags[i]);
        }
      }
      tokens.push({
        regex: copy(regex, {
          add: 'g' + (hasNativeY ? 'y' : '')
        }),
        handler: handler,
        scope: options.scope || defaultScope,
        flag: options.flag,
        reparse: options.reparse
      });
      self.cache.flush('patterns');
    };
    self.cache = function (pattern, flags) {
      var key = pattern + '***' + (flags || '');
      return cache[key] || (cache[key] = self(pattern, flags));
    };
    self.cache.flush = function (cacheName) {
      if (cacheName === 'patterns') {
        patternCache = {};
      } else {
        cache = {};
      }
    };
    self.escape = function (str) {
      return nativ.replace.call(toObject(str), /[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
    };
    self.exec = function (str, regex, pos, sticky) {
      var cacheFlags = 'g', match, r2;
      if (hasNativeY && (sticky || regex.sticky && sticky !== false)) {
        cacheFlags += 'y';
      }
      regex[REGEX_DATA] = regex[REGEX_DATA] || getBaseProps();
      r2 = regex[REGEX_DATA][cacheFlags] || (regex[REGEX_DATA][cacheFlags] = copy(regex, {
        add: cacheFlags,
        remove: sticky === false ? 'y' : ''
      }));
      r2.lastIndex = pos = pos || 0;
      match = fixed.exec.call(r2, str);
      if (sticky && match && match.index !== pos) {
        match = null;
      }
      if (regex.global) {
        regex.lastIndex = match ? r2.lastIndex : 0;
      }
      return match;
    };
    self.forEach = function (str, regex, callback, context) {
      var pos = 0, i = -1, match;
      while (match = self.exec(str, regex, pos)) {
        callback.call(context, match, ++i, str, regex);
        pos = match.index + (match[0].length || 1);
      }
      return context;
    };
    self.globalize = function (regex) {
      return copy(regex, {
        add: 'g',
        addProto: true
      });
    };
    self.install = function (options) {
      options = prepareOptions(options);
      if (!features.astral && options.astral) {
        setAstral(true);
      }
      if (!features.natives && options.natives) {
        setNatives(true);
      }
    };
    self.isInstalled = function (feature) {
      return !(!features[feature]);
    };
    self.isRegExp = function (value) {
      return toString.call(value) === '[object RegExp]';
    };
    self.match = function (str, regex, scope) {
      var global = regex.global && scope !== 'one' || scope === 'all', cacheFlags = (global ? 'g' : '') + (regex.sticky ? 'y' : ''), result, r2;
      regex[REGEX_DATA] = regex[REGEX_DATA] || getBaseProps();
      r2 = regex[REGEX_DATA][cacheFlags || 'noGY'] || (regex[REGEX_DATA][cacheFlags || 'noGY'] = copy(regex, {
        add: cacheFlags,
        remove: scope === 'one' ? 'g' : ''
      }));
      result = nativ.match.call(toObject(str), r2);
      if (regex.global) {
        regex.lastIndex = scope === 'one' && result ? result.index + result[0].length : 0;
      }
      return global ? result || [] : result && result[0];
    };
    self.matchChain = function (str, chain) {
      return function recurseChain(values, level) {
        var item = chain[level].regex ? chain[level] : {
            regex: chain[level]
          }, matches = [], addMatch = function (match) {
            if (item.backref) {
              if (!(match.hasOwnProperty(item.backref) || +item.backref < match.length)) {
                throw new ReferenceError('Backreference to undefined group: ' + item.backref);
              }
              matches.push(match[item.backref] || '');
            } else {
              matches.push(match[0]);
            }
          }, i;
        for (i = 0; i < values.length; ++i) {
          self.forEach(values[i], item.regex, addMatch);
        }
        return level === chain.length - 1 || !matches.length ? matches : recurseChain(matches, level + 1);
      }([
        str
      ], 0);
    };
    self.replace = function (str, search, replacement, scope) {
      var isRegex = self.isRegExp(search), global = search.global && scope !== 'one' || scope === 'all', cacheFlags = (global ? 'g' : '') + (search.sticky ? 'y' : ''), s2 = search, result;
      if (isRegex) {
        search[REGEX_DATA] = search[REGEX_DATA] || getBaseProps();
        s2 = search[REGEX_DATA][cacheFlags || 'noGY'] || (search[REGEX_DATA][cacheFlags || 'noGY'] = copy(search, {
          add: cacheFlags,
          remove: scope === 'one' ? 'g' : ''
        }));
      } else if (global) {
        s2 = new RegExp(self.escape(String(search)), 'g');
      }
      result = fixed.replace.call(toObject(str), s2, replacement);
      if (isRegex && search.global) {
        search.lastIndex = 0;
      }
      return result;
    };
    self.replaceEach = function (str, replacements) {
      var i, r;
      for (i = 0; i < replacements.length; ++i) {
        r = replacements[i];
        str = self.replace(str, r[0], r[1], r[2]);
      }
      return str;
    };
    self.split = function (str, separator, limit) {
      return fixed.split.call(toObject(str), separator, limit);
    };
    self.test = function (str, regex, pos, sticky) {
      return !(!self.exec(str, regex, pos, sticky));
    };
    self.uninstall = function (options) {
      options = prepareOptions(options);
      if (features.astral && options.astral) {
        setAstral(false);
      }
      if (features.natives && options.natives) {
        setNatives(false);
      }
    };
    self.union = function (patterns, flags) {
      var parts = /(\()(?!\?)|\\([1-9]\d*)|\\[\s\S]|\[(?:[^\\\]]|\\[\s\S])*]/g, output = [], numCaptures = 0, numPriorCaptures, captureNames, pattern, rewrite = function (match, paren, backref) {
          var name = captureNames[numCaptures - numPriorCaptures];
          if (paren) {
            ++numCaptures;
            if (name) {
              return '(?<' + name + '>';
            }
          } else if (backref) {
            return '\\' + (+backref + numPriorCaptures);
          }
          return match;
        }, i;
      if (!(isType(patterns, 'Array') && patterns.length)) {
        throw new TypeError('Must provide a nonempty array of patterns to merge');
      }
      for (i = 0; i < patterns.length; ++i) {
        pattern = patterns[i];
        if (self.isRegExp(pattern)) {
          numPriorCaptures = numCaptures;
          captureNames = pattern[REGEX_DATA] && pattern[REGEX_DATA].captureNames || [];
          output.push(nativ.replace.call(self(pattern.source).source, parts, rewrite));
        } else {
          output.push(self.escape(pattern));
        }
      }
      return self(output.join('|'), flags);
    };
    fixed.exec = function (str) {
      var origLastIndex = this.lastIndex, match = nativ.exec.apply(this, arguments), name, r2, i;
      if (match) {
        if (!correctExecNpcg && match.length > 1 && indexOf(match, '') > -1) {
          r2 = copy(this, {
            remove: 'g'
          });
          nativ.replace.call(String(str).slice(match.index), r2, function () {
            var len = arguments.length, i;
            for (i = 1; i < len - 2; ++i) {
              if (arguments[i] === undefined) {
                match[i] = undefined;
              }
            }
          });
        }
        if (this[REGEX_DATA] && this[REGEX_DATA].captureNames) {
          for (i = 1; i < match.length; ++i) {
            name = this[REGEX_DATA].captureNames[i - 1];
            if (name) {
              match[name] = match[i];
            }
          }
        }
        if (this.global && !match[0].length && this.lastIndex > match.index) {
          this.lastIndex = match.index;
        }
      }
      if (!this.global) {
        this.lastIndex = origLastIndex;
      }
      return match;
    };
    fixed.test = function (str) {
      return !(!fixed.exec.call(this, str));
    };
    fixed.match = function (regex) {
      var result;
      if (!self.isRegExp(regex)) {
        regex = new RegExp(regex);
      } else if (regex.global) {
        result = nativ.match.apply(this, arguments);
        regex.lastIndex = 0;
        return result;
      }
      return fixed.exec.call(regex, toObject(this));
    };
    fixed.replace = function (search, replacement) {
      var isRegex = self.isRegExp(search), origLastIndex, captureNames, result;
      if (isRegex) {
        if (search[REGEX_DATA]) {
          captureNames = search[REGEX_DATA].captureNames;
        }
        origLastIndex = search.lastIndex;
      } else {
        search += '';
      }
      if (isType(replacement, 'Function')) {
        result = nativ.replace.call(String(this), search, function () {
          var args = arguments, i;
          if (captureNames) {
            args[0] = new String(args[0]);
            for (i = 0; i < captureNames.length; ++i) {
              if (captureNames[i]) {
                args[0][captureNames[i]] = args[i + 1];
              }
            }
          }
          if (isRegex && search.global) {
            search.lastIndex = args[args.length - 2] + args[0].length;
          }
          return replacement.apply(undefined, args);
        });
      } else {
        result = nativ.replace.call(this == null ? this : String(this), search, function () {
          var args = arguments;
          return nativ.replace.call(String(replacement), replacementToken, function ($0, $1, $2) {
            var n;
            if ($1) {
              n = +$1;
              if (n <= args.length - 3) {
                return args[n] || '';
              }
              n = captureNames ? indexOf(captureNames, $1) : -1;
              if (n < 0) {
                throw new SyntaxError('Backreference to undefined group ' + $0);
              }
              return args[n + 1] || '';
            }
            if ($2 === '$') {
              return '$';
            }
            if ($2 === '&' || +$2 === 0) {
              return args[0];
            }
            if ($2 === '`') {
              return args[args.length - 1].slice(0, args[args.length - 2]);
            }
            if ($2 === '\'') {
              return args[args.length - 1].slice(args[args.length - 2] + args[0].length);
            }
            $2 = +$2;
            if (!isNaN($2)) {
              if ($2 > args.length - 3) {
                throw new SyntaxError('Backreference to undefined group ' + $0);
              }
              return args[$2] || '';
            }
            throw new SyntaxError('Invalid token ' + $0);
          });
        });
      }
      if (isRegex) {
        if (search.global) {
          search.lastIndex = 0;
        } else {
          search.lastIndex = origLastIndex;
        }
      }
      return result;
    };
    fixed.split = function (separator, limit) {
      if (!self.isRegExp(separator)) {
        return nativ.split.apply(this, arguments);
      }
      var str = String(this), output = [], origLastIndex = separator.lastIndex, lastLastIndex = 0, lastLength;
      limit = (limit === undefined ? -1 : limit) >>> 0;
      self.forEach(str, separator, function (match) {
        if (match.index + match[0].length > lastLastIndex) {
          output.push(str.slice(lastLastIndex, match.index));
          if (match.length > 1 && match.index < str.length) {
            Array.prototype.push.apply(output, match.slice(1));
          }
          lastLength = match[0].length;
          lastLastIndex = match.index + lastLength;
        }
      });
      if (lastLastIndex === str.length) {
        if (!nativ.test.call(separator, '') || lastLength) {
          output.push('');
        }
      } else {
        output.push(str.slice(lastLastIndex));
      }
      separator.lastIndex = origLastIndex;
      return output.length > limit ? output.slice(0, limit) : output;
    };
    add = self.addToken;
    add(/\\([ABCE-RTUVXYZaeg-mopqyz]|c(?![A-Za-z])|u(?![\dA-Fa-f]{4})|x(?![\dA-Fa-f]{2}))/, function (match, scope) {
      if (match[1] === 'B' && scope === defaultScope) {
        return match[0];
      }
      throw new SyntaxError('Invalid escape ' + match[0]);
    }, {
      scope: 'all'
    });
    add(/\[(\^?)]/, function (match) {
      return match[1] ? '[\\s\\S]' : '\\b\\B';
    });
    add(/\(\?#[^)]*\)/, function (match, scope, flags) {
      return isQuantifierNext(match.input, match.index + match[0].length, flags) ? '' : '(?:)';
    });
    add(/\s+|#.*/, function (match, scope, flags) {
      return isQuantifierNext(match.input, match.index + match[0].length, flags) ? '' : '(?:)';
    }, {
      flag: 'x'
    });
    add(/\./, function () {
      return '[\\s\\S]';
    }, {
      flag: 's'
    });
    add(/\\k<([\w$]+)>/, function (match) {
      var index = isNaN(match[1]) ? indexOf(this.captureNames, match[1]) + 1 : +match[1], endIndex = match.index + match[0].length;
      if (!index || index > this.captureNames.length) {
        throw new SyntaxError('Backreference to undefined group ' + match[0]);
      }
      return '\\' + index + (endIndex === match.input.length || isNaN(match.input.charAt(endIndex)) ? '' : '(?:)');
    });
    add(/\\(\d+)/, function (match, scope) {
      if (!(scope === defaultScope && /^[1-9]/.test(match[1]) && +match[1] <= this.captureNames.length) && match[1] !== '0') {
        throw new SyntaxError('Cannot use octal escape or backreference to undefined group ' + match[0]);
      }
      return match[0];
    }, {
      scope: 'all'
    });
    add(/\(\?P?<([\w$]+)>/, function (match) {
      if (!isNaN(match[1])) {
        throw new SyntaxError('Cannot use integer as capture name ' + match[0]);
      }
      if (match[1] === 'length' || match[1] === '__proto__') {
        throw new SyntaxError('Cannot use reserved word as capture name ' + match[0]);
      }
      if (indexOf(this.captureNames, match[1]) > -1) {
        throw new SyntaxError('Cannot use same name for multiple groups ' + match[0]);
      }
      this.captureNames.push(match[1]);
      this.hasNamedCapture = true;
      return '(';
    });
    add(/\((?!\?)/, function (match, scope, flags) {
      if (flags.indexOf('n') > -1) {
        return '(?:';
      }
      this.captureNames.push(null);
      return '(';
    }, {
      optionalFlags: 'n'
    });
    return self;
  }();
var Namespace = Shumway.AVM2.ABC.Namespace;
var Shumway;
(function (Shumway) {
  (function (AVM2) {
    (function (Runtime) {
      var Option = Shumway.Options.Option;
      var OptionSet = Shumway.Options.OptionSet;
      var runtimeOptions = systemOptions.register(new OptionSet('Runtime Options'));
      var traceScope = runtimeOptions.register(new Option('ts', 'traceScope', 'boolean', false, 'trace scope execution'));
      Runtime.traceExecution = runtimeOptions.register(new Option('tx', 'traceExecution', 'number', 0, 'trace script execution'));
      Runtime.traceCallExecution = runtimeOptions.register(new Option('txc', 'traceCallExecution', 'number', 0, 'trace call execution'));
      var functionBreak = runtimeOptions.register(new Option('fb', 'functionBreak', 'number', -1, 'Inserts a debugBreak at function index #.'));
      var compileOnly = runtimeOptions.register(new Option('co', 'compileOnly', 'number', -1, 'Compiles only function number.'));
      var compileUntil = runtimeOptions.register(new Option('cu', 'compileUntil', 'number', -1, 'Compiles only until a function number.'));
      Runtime.debuggerMode = runtimeOptions.register(new Option('dm', 'debuggerMode', 'boolean', false, 'matches avm2 debugger build semantics'));
      Runtime.enableVerifier = runtimeOptions.register(new Option('verify', 'verify', 'boolean', false, 'Enable verifier.'));
      Runtime.globalMultinameAnalysis = runtimeOptions.register(new Option('ga', 'globalMultinameAnalysis', 'boolean', false, 'Global multiname analysis.'));
      var traceInlineCaching = runtimeOptions.register(new Option('tic', 'traceInlineCaching', 'boolean', false, 'Trace inline caching execution.'));
      Runtime.codeCaching = runtimeOptions.register(new Option('cc', 'codeCaching', 'boolean', false, 'Enable code caching.'));
      var compilerEnableExceptions = runtimeOptions.register(new Option('cex', 'exceptions', 'boolean', false, 'Compile functions with catch blocks.'));
      var compilerMaximumMethodSize = runtimeOptions.register(new Option('cmms', 'maximumMethodSize', 'number', 4 * 1024, 'Compiler maximum method size.'));
      Runtime.traceClasses = runtimeOptions.register(new Option('tc', 'traceClasses', 'boolean', false, 'trace class creation'));
      Runtime.traceDomain = runtimeOptions.register(new Option('td', 'traceDomain', 'boolean', false, 'trace domain property access'));
      Runtime.sealConstTraits = false;
      Runtime.useAsAdd = true;
      var useSurrogates = true;
      var callCounter = new Shumway.Metrics.Counter(true);
      var Multiname = Shumway.AVM2.ABC.Multiname;
      var Namespace = Shumway.AVM2.ABC.Namespace;
      var MethodInfo = Shumway.AVM2.ABC.MethodInfo;
      var ClassInfo = Shumway.AVM2.ABC.ClassInfo;
      var InstanceInfo = Shumway.AVM2.ABC.InstanceInfo;
      var ScriptInfo = Shumway.AVM2.ABC.ScriptInfo;
      var SORT = Shumway.AVM2.ABC.SORT;
      var Trait = Shumway.AVM2.ABC.Trait;
      var IndentingWriter = Shumway.IndentingWriter;
      var hasOwnProperty = Shumway.ObjectUtilities.hasOwnProperty;
      var createMap = Shumway.ObjectUtilities.createMap;
      var cloneObject = Shumway.ObjectUtilities.cloneObject;
      var copyProperties = Shumway.ObjectUtilities.copyProperties;
      var createEmptyObject = Shumway.ObjectUtilities.createEmptyObject;
      var boxValue = Shumway.ObjectUtilities.boxValue;
      var bindSafely = Shumway.FunctionUtilities.bindSafely;
      var defineNonEnumerableGetterOrSetter = Shumway.ObjectUtilities.defineNonEnumerableGetterOrSetter;
      var defineNonEnumerableProperty = Shumway.ObjectUtilities.defineNonEnumerableProperty;
      var defineReadOnlyProperty = Shumway.ObjectUtilities.defineReadOnlyProperty;
      var defineNonEnumerableGetter = Shumway.ObjectUtilities.defineNonEnumerableGetter;
      var makeForwardingGetter = Shumway.FunctionUtilities.makeForwardingGetter;
      var makeForwardingSetter = Shumway.FunctionUtilities.makeForwardingSetter;
      var toSafeString = Shumway.StringUtilities.toSafeString;
      var toSafeArrayString = Shumway.StringUtilities.toSafeArrayString;
      var TRAIT = Shumway.AVM2.ABC.TRAIT;
      Runtime.VM_SLOTS = 'asSlots';
      Runtime.VM_LENGTH = 'asLength';
      Runtime.VM_BINDINGS = 'asBindings';
      Runtime.VM_NATIVE_PROTOTYPE_FLAG = 'asIsNative';
      Runtime.VM_OPEN_METHODS = 'asOpenMethods';
      Runtime.VM_IS_CLASS = 'asIsClass';
      Runtime.VM_IS_PROXY = 'asIsProxy';
      Runtime.VM_CALL_PROXY = 'asCallProxy';
      Runtime.VM_OPEN_METHOD_PREFIX = 'm';
      Runtime.VM_MEMOIZER_PREFIX = 'z';
      Runtime.VM_OPEN_SET_METHOD_PREFIX = 's';
      Runtime.VM_OPEN_GET_METHOD_PREFIX = 'g';
      Runtime.VM_NATIVE_BUILTIN_ORIGINALS = 'asOriginals';
      Runtime.VM_METHOD_OVERRIDES = createEmptyObject();
      var vmNextInterpreterFunctionId = 1;
      var vmNextCompiledFunctionId = 1;
      var totalFunctionCount = 0;
      var compiledFunctionCount = 0;
      var compilationCount = 0;
      function isClass(object) {
        true;
        return Object.hasOwnProperty.call(object, Runtime.VM_IS_CLASS);
      }
      Runtime.isClass = isClass;
      function isNativePrototype(object) {
        return Object.prototype.hasOwnProperty.call(object, Runtime.VM_NATIVE_PROTOTYPE_FLAG);
      }
      Runtime.isNativePrototype = isNativePrototype;
      var traitsWriter = null;
      var callWriter = null;
      function patch(patchTargets, value) {
        true;
        for (var i = 0; i < patchTargets.length; i++) {
          var patchTarget = patchTargets[i];
          if (Runtime.traceExecution.value >= 3) {
            var str = 'Patching: ';
            if (patchTarget.name) {
              str += patchTarget.name;
            } else if (patchTarget.get) {
              str += 'get ' + patchTarget.get;
            } else if (patchTarget.set) {
              str += 'set ' + patchTarget.set;
            }
            traitsWriter && traitsWriter.redLn(str);
          }
          if (patchTarget.get) {
            defineNonEnumerableGetterOrSetter(patchTarget.object, patchTarget.get, value, true);
          } else if (patchTarget.set) {
            defineNonEnumerableGetterOrSetter(patchTarget.object, patchTarget.set, value, false);
          } else {
            defineNonEnumerableProperty(patchTarget.object, patchTarget.name, value);
          }
        }
      }
      Runtime.patch = patch;
      function applyNonMemoizedMethodTrait(qn, trait, object, scope, natives) {
        true;
        if (trait.isMethod()) {
          var trampoline = Shumway.AVM2.Runtime.makeTrampoline(function (self) {
              var fn = getTraitFunction(trait, scope, natives);
              patch(self.patchTargets, fn);
              return fn;
            }, trait.methodInfo.parameters.length);
          trampoline.patchTargets = [
            {
              object: object,
              name: qn
            },
            {
              object: object,
              name: Runtime.VM_OPEN_METHOD_PREFIX + qn
            }
          ];
          var closure = bindSafely(trampoline, object);
          defineReadOnlyProperty(closure, Runtime.VM_LENGTH, trampoline.asLength);
          defineReadOnlyProperty(closure, Multiname.getPublicQualifiedName('prototype'), null);
          defineNonEnumerableProperty(object, qn, closure);
          defineNonEnumerableProperty(object, Runtime.VM_OPEN_METHOD_PREFIX + qn, closure);
        } else if (trait.isGetter() || trait.isSetter()) {
          var trampoline = Shumway.AVM2.Runtime.makeTrampoline(function (self) {
              var fn = getTraitFunction(trait, scope, natives);
              patch(self.patchTargets, fn);
              return fn;
            }, trait.isSetter() ? 1 : 0);
          if (trait.isGetter()) {
            trampoline.patchTargets = [
              {
                object: object,
                get: qn
              }
            ];
          } else {
            trampoline.patchTargets = [
              {
                object: object,
                set: qn
              }
            ];
          }
          defineNonEnumerableGetterOrSetter(object, qn, trampoline, trait.isGetter());
        } else {
          Shumway.Debug.unexpected(trait);
        }
      }
      Runtime.applyNonMemoizedMethodTrait = applyNonMemoizedMethodTrait;
      function applyMemoizedMethodTrait(qn, trait, object, scope, natives) {
        true;
        if (trait.isMethod()) {
          var memoizerTarget = {
              value: null
            };
          var trampoline = Shumway.AVM2.Runtime.makeTrampoline(function (self) {
              var fn = getTraitFunction(trait, scope, natives);
              patch(self.patchTargets, fn);
              return fn;
            }, trait.methodInfo.parameters.length, String(trait.name));
          memoizerTarget.value = trampoline;
          var openMethods = object.asOpenMethods;
          openMethods[qn] = trampoline;
          defineNonEnumerableProperty(object, Runtime.VM_OPEN_METHOD_PREFIX + qn, trampoline);
          defineNonEnumerableGetter(object, qn, Shumway.AVM2.Runtime.makeMemoizer(qn, memoizerTarget));
          trampoline.patchTargets = [
            {
              object: memoizerTarget,
              name: 'value'
            },
            {
              object: openMethods,
              name: qn
            },
            {
              object: object,
              name: Runtime.VM_OPEN_METHOD_PREFIX + qn
            }
          ];
        } else if (trait.isGetter() || trait.isSetter()) {
          var trampoline = Shumway.AVM2.Runtime.makeTrampoline(function (self) {
              var fn = getTraitFunction(trait, scope, natives);
              patch(self.patchTargets, fn);
              return fn;
            }, 0, String(trait.name));
          if (trait.isGetter()) {
            defineNonEnumerableProperty(object, Runtime.VM_OPEN_GET_METHOD_PREFIX + qn, trampoline);
            trampoline.patchTargets = [
              {
                object: object,
                get: qn
              },
              {
                object: object,
                name: Runtime.VM_OPEN_GET_METHOD_PREFIX + qn
              }
            ];
          } else {
            defineNonEnumerableProperty(object, Runtime.VM_OPEN_SET_METHOD_PREFIX + qn, trampoline);
            trampoline.patchTargets = [
              {
                object: object,
                set: qn
              },
              {
                object: object,
                name: Runtime.VM_OPEN_SET_METHOD_PREFIX + qn
              }
            ];
          }
          defineNonEnumerableGetterOrSetter(object, qn, trampoline, trait.isGetter());
        }
      }
      Runtime.applyMemoizedMethodTrait = applyMemoizedMethodTrait;
      function getNamespaceResolutionMap(namespaces) {
        var self = this;
        var map = self.resolutionMap[namespaces.runtimeId];
        if (map)
          return map;
        map = self.resolutionMap[namespaces.runtimeId] = Shumway.ObjectUtilities.createMap();
        var bindings = self.bindings;
        for (var key in bindings.map) {
          var multiname = key;
          var trait = bindings.map[key].trait;
          if (trait.isGetter() || trait.isSetter()) {
            multiname = multiname.substring(Shumway.AVM2.Runtime.Binding.KEY_PREFIX_LENGTH);
          }
          multiname = Multiname.fromQualifiedName(multiname);
          if (multiname.getNamespace().inNamespaceSet(namespaces)) {
            map[multiname.getName()] = Multiname.getQualifiedName(trait.name);
          }
        }
        return map;
      }
      Runtime.getNamespaceResolutionMap = getNamespaceResolutionMap;
      function resolveMultinameProperty(namespaces, name, flags) {
        var self = this;
        if (typeof name === 'object') {
          name = String(name);
        }
        if (Shumway.isNumeric(name)) {
          return Shumway.toNumber(name);
        }
        if (!namespaces) {
          return Multiname.getPublicQualifiedName(name);
        }
        if (namespaces.length > 1) {
          var resolved = self.getNamespaceResolutionMap(namespaces)[name];
          if (resolved)
            return resolved;
          return Multiname.getPublicQualifiedName(name);
        } else {
          return Multiname.qualifyName(namespaces[0], name);
        }
      }
      Runtime.resolveMultinameProperty = resolveMultinameProperty;
      function asGetPublicProperty(name) {
        var self = this;
        return self.asGetProperty(undefined, name, 0);
      }
      Runtime.asGetPublicProperty = asGetPublicProperty;
      function asGetProperty(namespaces, name, flags) {
        var self = this;
        var resolved = self.resolveMultinameProperty(namespaces, name, flags);
        if (self.asGetNumericProperty && Multiname.isNumeric(resolved)) {
          return self.asGetNumericProperty(resolved);
        }
        return self[resolved];
      }
      Runtime.asGetProperty = asGetProperty;
      function asGetPropertyLikelyNumeric(namespaces, name, flags) {
        var self = this;
        if (typeof name === 'number') {
          return self.asGetNumericProperty(name);
        }
        return asGetProperty.call(self, namespaces, name, flags);
      }
      Runtime.asGetPropertyLikelyNumeric = asGetPropertyLikelyNumeric;
      function asGetResolvedStringProperty(resolved) {
        true;
        return this[resolved];
      }
      Runtime.asGetResolvedStringProperty = asGetResolvedStringProperty;
      function asCallResolvedStringProperty(resolved, isLex, args) {
        var self = this;
        var receiver = isLex ? null : this;
        var openMethods = self.asOpenMethods;
        var method;
        if (receiver && openMethods && openMethods[resolved]) {
          method = openMethods[resolved];
        } else {
          method = self[resolved];
        }
        return method.apply(receiver, args);
      }
      Runtime.asCallResolvedStringProperty = asCallResolvedStringProperty;
      function asGetResolvedStringPropertyFallback(resolved) {
        var self = this;
        var name = Multiname.getNameFromPublicQualifiedName(resolved);
        return self.asGetProperty([
          Namespace.PUBLIC
        ], name, 0);
      }
      Runtime.asGetResolvedStringPropertyFallback = asGetResolvedStringPropertyFallback;
      function asSetPublicProperty(name, value) {
        var self = this;
        return self.asSetProperty(undefined, name, 0, value);
      }
      Runtime.asSetPublicProperty = asSetPublicProperty;
      function asSetProperty(namespaces, name, flags, value) {
        var self = this;
        if (typeof name === 'object') {
          name = String(name);
        }
        var resolved = self.resolveMultinameProperty(namespaces, name, flags);
        if (self.asSetNumericProperty && Multiname.isNumeric(resolved)) {
          return self.asSetNumericProperty(resolved, value);
        }
        var slotInfo = self.asSlots.byQN[resolved];
        if (slotInfo) {
          if (slotInfo.isConst) {
          }
          var type = slotInfo.type;
          if (type && type.coerce) {
            value = type.coerce(value);
          }
        }
        self[resolved] = value;
      }
      Runtime.asSetProperty = asSetProperty;
      function asSetPropertyLikelyNumeric(namespaces, name, flags, value) {
        var self = this;
        if (typeof name === 'number') {
          self.asSetNumericProperty(name, value);
          return;
        }
        return asSetProperty.call(self, namespaces, name, flags, value);
      }
      Runtime.asSetPropertyLikelyNumeric = asSetPropertyLikelyNumeric;
      function asDefinePublicProperty(name, descriptor) {
        var self = this;
        return self.asDefineProperty(undefined, name, 0, descriptor);
      }
      Runtime.asDefinePublicProperty = asDefinePublicProperty;
      function asDefineProperty(namespaces, name, flags, descriptor) {
        var self = this;
        if (typeof name === 'object') {
          name = String(name);
        }
        var resolved = self.resolveMultinameProperty(namespaces, name, flags);
        Object.defineProperty(self, resolved, descriptor);
      }
      Runtime.asDefineProperty = asDefineProperty;
      function asCallPublicProperty(name, args) {
        var self = this;
        return self.asCallProperty(undefined, name, 0, false, args);
      }
      Runtime.asCallPublicProperty = asCallPublicProperty;
      function asCallProperty(namespaces, name, flags, isLex, args) {
        var self = this;
        if (Runtime.traceCallExecution.value) {
          var receiverClassName = self.class ? self.class.className + ' ' : '';
          callWriter.enter('call ' + receiverClassName + name + '(' + toSafeArrayString(args) + ') #' + callCounter.count(name));
        }
        var receiver = isLex ? null : self;
        var result;
        if (isProxyObject(self)) {
          result = self[Runtime.VM_CALL_PROXY](new Multiname(namespaces, name, flags), receiver, args);
        } else {
          var method;
          var resolved = self.resolveMultinameProperty(namespaces, name, flags);
          if (self.asGetNumericProperty && Multiname.isNumeric(resolved)) {
            method = self.asGetNumericProperty(resolved);
          } else {
            var openMethods = self.asOpenMethods;
            if (receiver && openMethods && openMethods[resolved]) {
              method = openMethods[resolved];
            } else {
              method = self[resolved];
            }
          }
          result = method.apply(receiver, args);
        }
        Runtime.traceCallExecution.value > 0 && callWriter.leave('return ' + toSafeString(result));
        return result;
      }
      Runtime.asCallProperty = asCallProperty;
      function asCallSuper(scope, namespaces, name, flags, args) {
        var self = this;
        if (Runtime.traceCallExecution.value) {
          var receiverClassName = self.class ? self.class.className + ' ' : '';
          callWriter.enter('call super ' + receiverClassName + name + '(' + toSafeArrayString(args) + ') #' + callCounter.count(name));
        }
        var baseClass = scope.object.baseClass;
        var resolved = baseClass.traitsPrototype.resolveMultinameProperty(namespaces, name, flags);
        var openMethods = baseClass.traitsPrototype.asOpenMethods;
        var method = openMethods[resolved];
        var result = method.apply(this, args);
        Runtime.traceCallExecution.value > 0 && callWriter.leave('return ' + toSafeString(result));
        return result;
      }
      Runtime.asCallSuper = asCallSuper;
      function asSetSuper(scope, namespaces, name, flags, value) {
        var self = this;
        if (Runtime.traceCallExecution.value) {
          var receiverClassName = self.class ? self.class.className + ' ' : '';
          callWriter.enter('set super ' + receiverClassName + name + '(' + toSafeString(value) + ') #' + callCounter.count(name));
        }
        var baseClass = scope.object.baseClass;
        var resolved = baseClass.traitsPrototype.resolveMultinameProperty(namespaces, name, flags);
        if (self.asSlots.byQN[resolved]) {
          this.asSetProperty(namespaces, name, flags, value);
        } else {
          baseClass.traitsPrototype[Runtime.VM_OPEN_SET_METHOD_PREFIX + resolved].call(this, value);
        }
        Runtime.traceCallExecution.value > 0 && callWriter.leave('');
      }
      Runtime.asSetSuper = asSetSuper;
      function asGetSuper(scope, namespaces, name, flags) {
        var self = this;
        if (Runtime.traceCallExecution.value) {
          var receiver = self.class ? self.class.className + ' ' : '';
          callWriter.enter('get super ' + receiver + name + ' #' + callCounter.count(name));
        }
        var baseClass = scope.object.baseClass;
        var resolved = baseClass.traitsPrototype.resolveMultinameProperty(namespaces, name, flags);
        var result;
        if (self.asSlots.byQN[resolved]) {
          result = this.asGetProperty(namespaces, name, flags);
        } else {
          result = baseClass.traitsPrototype[Runtime.VM_OPEN_GET_METHOD_PREFIX + resolved].call(this);
        }
        Runtime.traceCallExecution.value > 0 && callWriter.leave('return ' + toSafeString(result));
        return result;
      }
      Runtime.asGetSuper = asGetSuper;
      function construct(cls, args) {
        if (cls.classInfo) {
          var qn = Multiname.getQualifiedName(cls.classInfo.instanceInfo.name);
          if (qn === Multiname.String) {
            return String.apply(null, args);
          }
          if (qn === Multiname.Boolean) {
            return Boolean.apply(null, args);
          }
          if (qn === Multiname.Number) {
            return Number.apply(null, args);
          }
        }
        var c = cls.instanceConstructor;
        var a = args;
        switch (args.length) {
        case 0:
          return new c();
        case 1:
          return new c(a[0]);
        case 2:
          return new c(a[0], a[1]);
        case 3:
          return new c(a[0], a[1], a[2]);
        case 4:
          return new c(a[0], a[1], a[2], a[3]);
        case 5:
          return new c(a[0], a[1], a[2], a[3], a[4]);
        case 6:
          return new c(a[0], a[1], a[2], a[3], a[4], a[5]);
        case 7:
          return new c(a[0], a[1], a[2], a[3], a[4], a[5], a[6]);
        case 8:
          return new c(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
        case 9:
          return new c(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]);
        case 10:
          return new c(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]);
        }
        var applyArguments = [];
        for (var i = 0; i < args.length; i++) {
          applyArguments[i + 1] = args[i];
        }
        return new (Function.bind.apply(c, applyArguments))();
      }
      Runtime.construct = construct;
      function asConstructProperty(namespaces, name, flags, args) {
        var self = this;
        var constructor = self.asGetProperty(namespaces, name, flags);
        if (Runtime.traceCallExecution.value) {
          callWriter.enter('construct ' + name + '(' + toSafeArrayString(args) + ') #' + callCounter.count(name));
        }
        var result = construct(constructor, args);
        Runtime.traceCallExecution.value > 0 && callWriter.leave('return ' + toSafeString(result));
        return result;
      }
      Runtime.asConstructProperty = asConstructProperty;
      function nonProxyingHasProperty(object, name) {
        return name in object;
      }
      Runtime.nonProxyingHasProperty = nonProxyingHasProperty;
      function asHasProperty(namespaces, name, flags, nonProxy) {
        var self = this;
        if (self.hasProperty) {
          return self.hasProperty(namespaces, name, flags);
        }
        if (nonProxy) {
          return nonProxyingHasProperty(self, self.resolveMultinameProperty(namespaces, name, flags));
        } else {
          return self.resolveMultinameProperty(namespaces, name, flags) in this;
        }
      }
      Runtime.asHasProperty = asHasProperty;
      function asDeleteProperty(namespaces, name, flags) {
        var self = this;
        if (self.asHasTraitProperty(namespaces, name, flags)) {
          return false;
        }
        var resolved = self.resolveMultinameProperty(namespaces, name, flags);
        return delete self[resolved];
      }
      Runtime.asDeleteProperty = asDeleteProperty;
      function asHasTraitProperty(namespaces, name, flags) {
        var self = this;
        var resolved = self.resolveMultinameProperty(namespaces, name, flags);
        return self.asBindings.indexOf(resolved) >= 0;
      }
      Runtime.asHasTraitProperty = asHasTraitProperty;
      function asGetNumericProperty(i) {
        return this[i];
      }
      Runtime.asGetNumericProperty = asGetNumericProperty;
      function asSetNumericProperty(i, v) {
        this[i] = v;
      }
      Runtime.asSetNumericProperty = asSetNumericProperty;
      function asGetDescendants(namespaces, name, flags) {
        Shumway.Debug.notImplemented('asGetDescendants');
      }
      Runtime.asGetDescendants = asGetDescendants;
      function asNextNameIndex(index) {
        var self = this;
        if (index === 0) {
          defineNonEnumerableProperty(self, 'asEnumerableKeys', self.asGetEnumerableKeys());
        }
        var asEnumerableKeys = self.asEnumerableKeys;
        while (index < asEnumerableKeys.length) {
          if (self.asHasProperty(undefined, asEnumerableKeys[index], 0)) {
            return index + 1;
          }
          index++;
        }
        return 0;
      }
      Runtime.asNextNameIndex = asNextNameIndex;
      function asNextName(index) {
        var self = this;
        var asEnumerableKeys = self.asEnumerableKeys;
        true;
        return asEnumerableKeys[index - 1];
      }
      Runtime.asNextName = asNextName;
      function asNextValue(index) {
        return this.asGetPublicProperty(this.asNextName(index));
      }
      Runtime.asNextValue = asNextValue;
      function asGetEnumerableKeys() {
        var self = this;
        var boxedValue = self.valueOf();
        if (typeof boxedValue === 'string' || typeof boxedValue === 'number') {
          return [];
        }
        var keys = Object.keys(this);
        var result = [];
        for (var i = 0; i < keys.length; i++) {
          var key = keys[i];
          if (Shumway.isNumeric(key)) {
            result.push(key);
          } else {
            var name = Multiname.stripPublicQualifier(key);
            if (name !== undefined) {
              result.push(name);
            }
          }
        }
        return result;
      }
      Runtime.asGetEnumerableKeys = asGetEnumerableKeys;
      function asTypeOf(x) {
        if (x) {
          if (x.constructor === String) {
            return 'string';
          } else if (x.constructor === Number) {
            return 'number';
          } else if (x.constructor === Boolean) {
            return 'boolean';
          } else if (x instanceof XML || x instanceof XMLList) {
            return 'xml';
          }
        }
        return typeof x;
      }
      Runtime.asTypeOf = asTypeOf;
      function publicizeProperties(object) {
        var keys = Object.keys(object);
        for (var i = 0; i < keys.length; i++) {
          var k = keys[i];
          if (!Multiname.isPublicQualifiedName(k)) {
            var v = object[k];
            object[Multiname.getPublicQualifiedName(k)] = v;
            delete object[k];
          }
        }
      }
      Runtime.publicizeProperties = publicizeProperties;
      function asGetSlot(object, index) {
        return object[object.asSlots.byID[index].name];
      }
      Runtime.asGetSlot = asGetSlot;
      function asSetSlot(object, index, value) {
        var slotInfo = object.asSlots.byID[index];
        if (slotInfo.const) {
          return;
        }
        var name = slotInfo.name;
        var type = slotInfo.type;
        if (type && type.coerce) {
          object[name] = type.coerce(value);
        } else {
          object[name] = value;
        }
      }
      Runtime.asSetSlot = asSetSlot;
      function throwError(name, error) {
        if (true) {
          var message = Shumway.AVM2.formatErrorMessage.apply(null, Array.prototype.slice.call(arguments, 1));
          throwErrorFromVM(Shumway.AVM2.Runtime.AVM2.currentDomain(), name, message, error.code);
        } else {
          throwErrorFromVM(Shumway.AVM2.Runtime.AVM2.currentDomain(), name, Shumway.AVM2.getErrorMessage(error.code), error.code);
        }
      }
      Runtime.throwError = throwError;
      function throwErrorFromVM(domain, errorClass, message, id) {
        var error = new (domain.getClass(errorClass)).instanceConstructor(message, id);
        throw error;
      }
      Runtime.throwErrorFromVM = throwErrorFromVM;
      function translateError(domain, error) {
        if (error instanceof Error) {
          var type = domain.getClass(error.name);
          if (type) {
            return new type.instanceConstructor(Shumway.AVM2.translateErrorMessage(error));
          }
          Shumway.Debug.unexpected('Can\'t translate error: ' + error);
        }
        return error;
      }
      Runtime.translateError = translateError;
      function asIsInstanceOf(type, value) {
        return type.isInstanceOf(value);
      }
      Runtime.asIsInstanceOf = asIsInstanceOf;
      function asIsType(type, value) {
        return type.isInstance(value);
      }
      Runtime.asIsType = asIsType;
      function asAsType(type, value) {
        return asIsType(type, value) ? value : null;
      }
      Runtime.asAsType = asAsType;
      function asCoerceByMultiname(domain, multiname, value) {
        true;
        switch (Multiname.getQualifiedName(multiname)) {
        case Multiname.Int:
          return asCoerceInt(value);
        case Multiname.Uint:
          return asCoerceUint(value);
        case Multiname.String:
          return asCoerceString(value);
        case Multiname.Number:
          return asCoerceNumber(value);
        case Multiname.Boolean:
          return asCoerceBoolean(value);
        case Multiname.Object:
          return asCoerceObject(value);
        }
        return asCoerce(domain.getType(multiname), value);
      }
      Runtime.asCoerceByMultiname = asCoerceByMultiname;
      function asCoerce(type, value) {
        if (type.coerce) {
          return type.coerce(value);
        }
        if (Shumway.isNullOrUndefined(value)) {
          return null;
        }
        if (type.isInstance(value)) {
          return value;
        } else {
          true;
        }
      }
      Runtime.asCoerce = asCoerce;
      function asCoerceString(x) {
        if (typeof x === 'string') {
          return x;
        } else if (x == undefined) {
          return null;
        }
        return x + '';
      }
      Runtime.asCoerceString = asCoerceString;
      function asCoerceInt(x) {
        return x | 0;
      }
      Runtime.asCoerceInt = asCoerceInt;
      function asCoerceUint(x) {
        return x >>> 0;
      }
      Runtime.asCoerceUint = asCoerceUint;
      function asCoerceNumber(x) {
        return +x;
      }
      Runtime.asCoerceNumber = asCoerceNumber;
      function asCoerceBoolean(x) {
        return !(!x);
      }
      Runtime.asCoerceBoolean = asCoerceBoolean;
      function asCoerceObject(x) {
        if (x == undefined) {
          return null;
        }
        if (typeof x === 'string' || typeof x === 'number') {
          return x;
        }
        return Object(x);
      }
      Runtime.asCoerceObject = asCoerceObject;
      function asDefaultCompareFunction(a, b) {
        return String(a).localeCompare(String(b));
      }
      Runtime.asDefaultCompareFunction = asDefaultCompareFunction;
      function asCompare(a, b, options, compareFunction) {
        true;
        true;
        var result = 0;
        if (!compareFunction) {
          compareFunction = asDefaultCompareFunction;
        }
        if (options & 1) {
          a = String(a).toLowerCase();
          b = String(b).toLowerCase();
        }
        if (options & 16) {
          a = Shumway.toNumber(a);
          b = Shumway.toNumber(b);
          result = a < b ? -1 : a > b ? 1 : 0;
        } else {
          result = compareFunction(a, b);
        }
        if (options & 2) {
          result *= -1;
        }
        return result;
      }
      Runtime.asCompare = asCompare;
      function asAdd(l, r) {
        if (typeof l === 'string' || typeof r === 'string') {
          return String(l) + String(r);
        }
        return l + r;
      }
      Runtime.asAdd = asAdd;
      function asHasNext2(object, index) {
        if (Shumway.isNullOrUndefined(object)) {
          return {
            index: 0,
            object: null
          };
        }
        object = boxValue(object);
        var nextIndex = object.asNextNameIndex(index);
        if (nextIndex > 0) {
          return {
            index: nextIndex,
            object: object
          };
        }
        while (true) {
          var object = Object.getPrototypeOf(object);
          if (!object) {
            return {
              index: 0,
              object: null
            };
          }
          nextIndex = object.asNextNameIndex(0);
          if (nextIndex > 0) {
            return {
              index: nextIndex,
              object: object
            };
          }
        }
        return {
          index: 0,
          object: null
        };
      }
      Runtime.asHasNext2 = asHasNext2;
      function getDescendants(object, mn) {
        if (!isXMLType(object)) {
          throw 'Not XML object in getDescendants';
        }
        return object.descendants(mn);
      }
      Runtime.getDescendants = getDescendants;
      function checkFilter(value) {
        if (!value.class || !isXMLType(value)) {
          throw 'TypeError operand of childFilter not of XML type';
        }
        return value;
      }
      Runtime.checkFilter = checkFilter;
      function initializeGlobalObject(global) {
        var VM_NATIVE_BUILTIN_SURROGATES = [
            {
              name: 'Object',
              methods: [
                'toString',
                'valueOf'
              ]
            },
            {
              name: 'Function',
              methods: [
                'toString',
                'valueOf'
              ]
            }
          ];
        var originals = global[Runtime.VM_NATIVE_BUILTIN_ORIGINALS] = createEmptyObject();
        VM_NATIVE_BUILTIN_SURROGATES.forEach(function (surrogate) {
          var object = global[surrogate.name];
          originals[surrogate.name] = createEmptyObject();
          surrogate.methods.forEach(function (originalFunctionName) {
            var originalFunction;
            if (object.prototype.hasOwnProperty(originalFunctionName)) {
              originalFunction = object.prototype[originalFunctionName];
            } else {
              originalFunction = originals['Object'][originalFunctionName];
            }
            originals[surrogate.name][originalFunctionName] = originalFunction;
            var overrideFunctionName = Multiname.getPublicQualifiedName(originalFunctionName);
            if (useSurrogates) {
              global[surrogate.name].prototype[originalFunctionName] = function surrogate() {
                if (this[overrideFunctionName]) {
                  return this[overrideFunctionName]();
                }
                return originalFunction.call(this);
              };
            }
          });
        });
        [
          'Object',
          'Number',
          'Boolean',
          'String',
          'Array',
          'Date',
          'RegExp'
        ].forEach(function (name) {
          defineReadOnlyProperty(global[name].prototype, Runtime.VM_NATIVE_PROTOTYPE_FLAG, true);
        });
        defineNonEnumerableProperty(global.Object.prototype, 'getNamespaceResolutionMap', getNamespaceResolutionMap);
        defineNonEnumerableProperty(global.Object.prototype, 'resolveMultinameProperty', resolveMultinameProperty);
        defineNonEnumerableProperty(global.Object.prototype, 'asGetProperty', asGetProperty);
        defineNonEnumerableProperty(global.Object.prototype, 'asGetPublicProperty', asGetPublicProperty);
        defineNonEnumerableProperty(global.Object.prototype, 'asGetResolvedStringProperty', asGetResolvedStringProperty);
        defineNonEnumerableProperty(global.Object.prototype, 'asSetProperty', asSetProperty);
        defineNonEnumerableProperty(global.Object.prototype, 'asSetPublicProperty', asSetPublicProperty);
        defineNonEnumerableProperty(global.Object.prototype, 'asDefineProperty', asDefineProperty);
        defineNonEnumerableProperty(global.Object.prototype, 'asDefinePublicProperty', asDefinePublicProperty);
        defineNonEnumerableProperty(global.Object.prototype, 'asCallProperty', asCallProperty);
        defineNonEnumerableProperty(global.Object.prototype, 'asCallSuper', asCallSuper);
        defineNonEnumerableProperty(global.Object.prototype, 'asGetSuper', asGetSuper);
        defineNonEnumerableProperty(global.Object.prototype, 'asSetSuper', asSetSuper);
        defineNonEnumerableProperty(global.Object.prototype, 'asCallPublicProperty', asCallPublicProperty);
        defineNonEnumerableProperty(global.Object.prototype, 'asCallResolvedStringProperty', asCallResolvedStringProperty);
        defineNonEnumerableProperty(global.Object.prototype, 'asConstructProperty', asConstructProperty);
        defineNonEnumerableProperty(global.Object.prototype, 'asHasProperty', asHasProperty);
        defineNonEnumerableProperty(global.Object.prototype, 'asHasTraitProperty', asHasTraitProperty);
        defineNonEnumerableProperty(global.Object.prototype, 'asDeleteProperty', asDeleteProperty);
        defineNonEnumerableProperty(global.Object.prototype, 'asNextName', asNextName);
        defineNonEnumerableProperty(global.Object.prototype, 'asNextValue', asNextValue);
        defineNonEnumerableProperty(global.Object.prototype, 'asNextNameIndex', asNextNameIndex);
        defineNonEnumerableProperty(global.Object.prototype, 'asGetEnumerableKeys', asGetEnumerableKeys);
        [
          'Array',
          'Int8Array',
          'Uint8Array',
          'Uint8ClampedArray',
          'Int16Array',
          'Uint16Array',
          'Int32Array',
          'Uint32Array',
          'Float32Array',
          'Float64Array'
        ].forEach(function (name) {
          if (!(name in global)) {
            log(name + ' was not found in globals');
            return;
          }
          defineNonEnumerableProperty(global[name].prototype, 'asGetNumericProperty', asGetNumericProperty);
          defineNonEnumerableProperty(global[name].prototype, 'asSetNumericProperty', asSetNumericProperty);
          defineNonEnumerableProperty(global[name].prototype, 'asGetProperty', asGetPropertyLikelyNumeric);
          defineNonEnumerableProperty(global[name].prototype, 'asSetProperty', asSetPropertyLikelyNumeric);
        });
        global.Array.prototype.asGetProperty = function (namespaces, name, flags) {
          if (typeof name === 'number') {
            return this[name];
          }
          return asGetProperty.call(this, namespaces, name, flags);
        };
        global.Array.prototype.asSetProperty = function (namespaces, name, flags, value) {
          if (typeof name === 'number') {
            this[name] = value;
            return;
          }
          return asSetProperty.call(this, namespaces, name, flags, value);
        };
      }
      Runtime.initializeGlobalObject = initializeGlobalObject;
      function nameInTraits(object, qn) {
        if (object.hasOwnProperty(Runtime.VM_BINDINGS) && object.hasOwnProperty(qn)) {
          return true;
        }
        var proto = Object.getPrototypeOf(object);
        return proto.hasOwnProperty(Runtime.VM_BINDINGS) && proto.hasOwnProperty(qn);
      }
      Runtime.nameInTraits = nameInTraits;
      function CatchScopeObject(domain, trait) {
        if (trait) {
          new Shumway.AVM2.Runtime.CatchBindings(new Shumway.AVM2.Runtime.Scope(null, this), trait).applyTo(domain, this);
        }
      }
      Runtime.CatchScopeObject = CatchScopeObject;
      var Global = function () {
          function Global(script) {
            this.scriptInfo = script;
            script.global = this;
            this.scriptBindings = new Shumway.AVM2.Runtime.ScriptBindings(script, new Shumway.AVM2.Runtime.Scope(null, this, false));
            this.scriptBindings.applyTo(script.abc.applicationDomain, this);
            script.loaded = true;
          }
          Global.prototype.toString = function () {
            return '[object global]';
          };
          Global.prototype.isExecuted = function () {
            return this.scriptInfo.executed;
          };
          Global.prototype.isExecuting = function () {
            return this.scriptInfo.executing;
          };
          Global.prototype.ensureExecuted = function () {
            Shumway.AVM2.Runtime.ensureScriptIsExecuted(this.scriptInfo);
          };
          return Global;
        }();
      Runtime.Global = Global;
      defineNonEnumerableProperty(Global.prototype, Multiname.getPublicQualifiedName('toString'), function () {
        return this.toString();
      });
      var LazyInitializer = function () {
          function LazyInitializer(target) {
            this.target = target;
          }
          LazyInitializer.create = function (target) {
            if (target.asLazyInitializer) {
              return target.asLazyInitializer;
            }
            return target.asLazyInitializer = new LazyInitializer(target);
          };
          LazyInitializer.prototype.getName = function () {
            if (this.name) {
              return this.name;
            }
            var target = this.target, initialize;
            if (this.target instanceof ScriptInfo) {
              var scriptInfo = target;
              this.name = '$' + Shumway.StringUtilities.variableLengthEncodeInt32(scriptInfo.hash);
              initialize = function () {
                Shumway.AVM2.Runtime.ensureScriptIsExecuted(target, 'Lazy Initializer');
                return scriptInfo.global;
              };
            } else if (this.target instanceof ClassInfo) {
              var classInfo = target;
              this.name = '$' + Shumway.StringUtilities.variableLengthEncodeInt32(classInfo.hash);
              initialize = function () {
                if (classInfo.classObject) {
                  return classInfo.classObject;
                }
                return classInfo.abc.applicationDomain.getProperty(classInfo.instanceInfo.name);
              };
            } else {
              Shumway.Debug.notImplemented(String(target));
            }
            var name = this.name;
            Object.defineProperty(LazyInitializer._holder, name, {
              get: function () {
                var value = initialize();
                Object.defineProperty(LazyInitializer._holder, name, {
                  value: value,
                  writable: true
                });
                return value;
              },
              configurable: true
            });
            return name;
          };
          LazyInitializer._holder = jsGlobal;
          return LazyInitializer;
        }();
      Runtime.LazyInitializer = LazyInitializer;
      function forEachPublicProperty(object, fn, self) {
        if (!object.asBindings) {
          for (var key in object) {
            fn.call(self, key, object[key]);
          }
          return;
        }
        for (var key in object) {
          if (Shumway.isNumeric(key)) {
            fn.call(self, key, object[key]);
          } else if (Multiname.isPublicQualifiedName(key) && object.asBindings.indexOf(key) < 0) {
            var name = Multiname.stripPublicQualifier(key);
            fn.call(self, name, object[key]);
          }
        }
      }
      Runtime.forEachPublicProperty = forEachPublicProperty;
      function wrapJSObject(object) {
        var wrapper = Object.create(object);
        for (var i in object) {
          Object.defineProperty(wrapper, Multiname.getPublicQualifiedName(i), function (object, i) {
            return {
              get: function () {
                return object[i];
              },
              set: function (value) {
                object[i] = value;
              },
              enumerable: true
            };
          }(object, i));
        }
        return wrapper;
      }
      Runtime.wrapJSObject = wrapJSObject;
      function asCreateActivation(methodInfo) {
        return Object.create(methodInfo.activationPrototype);
      }
      Runtime.asCreateActivation = asCreateActivation;
      var GlobalMultinameResolver = function () {
          function GlobalMultinameResolver() {
          }
          GlobalMultinameResolver.updateTraits = function (traits) {
            for (var i = 0; i < traits.length; i++) {
              var trait = traits[i];
              var name = trait.name.name;
              var namespace = trait.name.getNamespace();
              if (!namespace.isDynamic()) {
                GlobalMultinameResolver.hasNonDynamicNamespaces[name] = true;
                if (GlobalMultinameResolver.wasResolved[name]) {
                  Shumway.Debug.notImplemented('We have to the undo the optimization, ' + name + ' can now bind to ' + namespace);
                }
              }
            }
          };
          GlobalMultinameResolver.loadAbc = function (abc) {
            if (!Runtime.globalMultinameAnalysis.value) {
              return;
            }
            var scripts = abc.scripts;
            var classes = abc.classes;
            var methods = abc.methods;
            for (var i = 0; i < scripts.length; i++) {
              GlobalMultinameResolver.updateTraits(scripts[i].traits);
            }
            for (var i = 0; i < classes.length; i++) {
              GlobalMultinameResolver.updateTraits(classes[i].traits);
              GlobalMultinameResolver.updateTraits(classes[i].instanceInfo.traits);
            }
            for (var i = 0; i < methods.length; i++) {
              if (methods[i].traits) {
                GlobalMultinameResolver.updateTraits(methods[i].traits);
              }
            }
          };
          GlobalMultinameResolver.resolveMultiname = function (multiname) {
            var name = multiname.name;
            if (GlobalMultinameResolver.hasNonDynamicNamespaces[name]) {
              return;
            }
            GlobalMultinameResolver.wasResolved[name] = true;
            return new Multiname([
              Namespace.PUBLIC
            ], multiname.name);
          };
          GlobalMultinameResolver.hasNonDynamicNamespaces = createEmptyObject();
          GlobalMultinameResolver.wasResolved = createEmptyObject();
          return GlobalMultinameResolver;
        }();
      Runtime.GlobalMultinameResolver = GlobalMultinameResolver;
      var ActivationInfo = function () {
          function ActivationInfo(methodInfo) {
            this.methodInfo = methodInfo;
          }
          return ActivationInfo;
        }();
      Runtime.ActivationInfo = ActivationInfo;
      function sliceArguments(args, offset) {
        if (typeof offset === 'undefined') {
          offset = 0;
        }
        return Array.prototype.slice.call(args, offset);
      }
      Runtime.sliceArguments = sliceArguments;
      function canCompile(mi) {
        if (!mi.hasBody) {
          return false;
        }
        if (mi.hasExceptions() && !compilerEnableExceptions.value) {
          return false;
        } else if (mi.code.length > compilerMaximumMethodSize.value) {
          return false;
        }
        return true;
      }
      Runtime.canCompile = canCompile;
      function shouldCompile(mi) {
        if (!canCompile(mi)) {
          return false;
        }
        if (mi.isClassInitializer || mi.isScriptInitializer) {
          return false;
        }
        return true;
      }
      Runtime.shouldCompile = shouldCompile;
      function forceCompile(mi) {
        if (mi.hasExceptions()) {
          return false;
        }
        var holder = mi.holder;
        if (holder instanceof ClassInfo) {
          holder = holder.instanceInfo;
        }
        if (holder instanceof InstanceInfo) {
          var packageName = holder.name.namespaces[0].uri;
          switch (packageName) {
          case 'flash.geom':
          case 'flash.events':
            return true;
          default:
            break;
          }
          var className = holder.name.getOriginalName();
          switch (className) {
          case 'com.google.youtube.model.VideoData':
            return true;
          }
        }
        return false;
      }
      Runtime.forceCompile = forceCompile;
      Runtime.CODE_CACHE = createEmptyObject();
      function searchCodeCache(methodInfo) {
        if (!Runtime.codeCaching.value) {
          return;
        }
        var cacheInfo = Runtime.CODE_CACHE[methodInfo.abc.hash];
        if (!cacheInfo) {
          warn('Cannot Find Code Cache For ABC, name: ' + methodInfo.abc.name + ', hash: ' + methodInfo.abc.hash);
          Counter.count('Code Cache ABC Miss');
          return;
        }
        if (!cacheInfo.isInitialized) {
          methodInfo.abc.scripts.forEach(function (scriptInfo) {
            LazyInitializer.create(scriptInfo).getName();
          });
          methodInfo.abc.classes.forEach(function (classInfo) {
            LazyInitializer.create(classInfo).getName();
          });
          cacheInfo.isInitialized = true;
        }
        var method = cacheInfo.methods[methodInfo.index];
        if (!method) {
          if (methodInfo.isInstanceInitializer || methodInfo.isClassInitializer) {
            Counter.count('Code Cache Query On Initializer');
          } else {
            Counter.count('Code Cache MISS ON OTHER');
            warn('Shouldn\'t MISS: ' + methodInfo + ' ' + methodInfo.debugName);
          }
          Counter.count('Code Cache Miss');
          return;
        }
        log('Linking CC: ' + methodInfo);
        Counter.count('Code Cache Hit');
        return method;
      }
      Runtime.searchCodeCache = searchCodeCache;
      function createInterpretedFunction(methodInfo, scope, hasDynamicScope) {
        var mi = methodInfo;
        var hasDefaults = false;
        var defaults = mi.parameters.map(function (p) {
            if (p.value !== undefined) {
              hasDefaults = true;
            }
            return p.value;
          });
        var fn;
        if (hasDynamicScope) {
          fn = function (scope) {
            var global = this === jsGlobal ? scope.global.object : this;
            var args = sliceArguments(arguments, 1);
            if (hasDefaults && args.length < defaults.length) {
              args = args.concat(defaults.slice(args.length - defaults.length));
            }
            return Shumway.AVM2.Interpreter.interpretMethod(global, methodInfo, scope, args);
          };
        } else {
          fn = function () {
            var global = this === jsGlobal ? scope.global.object : this;
            var args = sliceArguments(arguments);
            if (hasDefaults && args.length < defaults.length) {
              args = args.concat(defaults.slice(arguments.length - defaults.length));
            }
            return Shumway.AVM2.Interpreter.interpretMethod(global, methodInfo, scope, args);
          };
        }
        fn.instanceConstructor = fn;
        fn.debugName = 'Interpreter Function #' + vmNextInterpreterFunctionId++;
        return fn;
      }
      Runtime.createInterpretedFunction = createInterpretedFunction;
      function debugName(value) {
        if (Shumway.isFunction(value)) {
          return value.debugName;
        }
        return value;
      }
      Runtime.debugName = debugName;
      function createCompiledFunction(methodInfo, scope, hasDynamicScope, breakpoint, deferCompilation) {
        var mi = methodInfo;
        var cached = searchCodeCache(mi);
        if (!cached) {
          var result = Compiler.compileMethod(mi, scope, hasDynamicScope);
          var parameters = result.parameters;
          var body = result.body;
        }
        var fnName = mi.name ? Multiname.getQualifiedName(mi.name) : 'fn' + compiledFunctionCount;
        if (mi.holder) {
          var fnNamePrefix = '';
          if (mi.holder instanceof ClassInfo) {
            fnNamePrefix = 'static$' + mi.holder.instanceInfo.name.getName();
          } else if (mi.holder instanceof InstanceInfo) {
            fnNamePrefix = mi.holder.name.getName();
          } else if (mi.holder instanceof ScriptInfo) {
            fnNamePrefix = 'script';
          }
          fnName = fnNamePrefix + '$' + fnName;
        }
        fnName = Shumway.StringUtilities.escapeString(fnName);
        if (mi.verified) {
          fnName += '$V';
        }
        if (compiledFunctionCount == functionBreak.value || breakpoint) {
          body = '{ debugger; \n' + body + '}';
        }
        if (!cached) {
          var fnSource = 'function ' + fnName + ' (' + parameters.join(', ') + ') ' + body;
        }
        if (traceLevel.value > 1) {
          mi.trace(new IndentingWriter(), mi.abc);
        }
        mi.debugTrace = function () {
          mi.trace(new IndentingWriter(), mi.abc);
        };
        if (traceLevel.value > 0) {
          log(fnSource);
        }
        var fn = cached || new Function('return ' + fnSource)();
        fn.debugName = 'Compiled Function #' + vmNextCompiledFunctionId++;
        return fn;
      }
      Runtime.createCompiledFunction = createCompiledFunction;
      function createFunction(mi, scope, hasDynamicScope, breakpoint) {
        if (typeof breakpoint === 'undefined') {
          breakpoint = false;
        }
        true;
        if (mi.freeMethod) {
          if (hasDynamicScope) {
            return Shumway.AVM2.Runtime.bindFreeMethodScope(mi, scope);
          }
          return mi.freeMethod;
        }
        var fn;
        if (fn = Shumway.AVM2.Runtime.checkMethodOverrides(mi)) {
          true;
          return fn;
        }
        ensureFunctionIsInitialized(mi);
        totalFunctionCount++;
        var useInterpreter = false;
        if ((mi.abc.applicationDomain.mode === 1 || !shouldCompile(mi)) && !forceCompile(mi)) {
          useInterpreter = true;
        }
        if (compileOnly.value >= 0) {
          if (Number(compileOnly.value) !== totalFunctionCount) {
            log('Compile Only Skipping ' + totalFunctionCount);
            useInterpreter = true;
          }
        }
        if (compileUntil.value >= 0) {
          if (totalFunctionCount > 1000) {
            log(Shumway.Debug.backtrace());
            log(Shumway.AVM2.Runtime.AVM2.getStackTrace());
          }
          if (totalFunctionCount > compileUntil.value) {
            log('Compile Until Skipping ' + totalFunctionCount);
            useInterpreter = true;
          }
        }
        if (useInterpreter) {
          mi.freeMethod = createInterpretedFunction(mi, scope, hasDynamicScope);
        } else {
          compiledFunctionCount++;
          if (compileOnly.value >= 0 || compileUntil.value >= 0) {
            log('Compiling ' + totalFunctionCount);
          }
          mi.freeMethod = createCompiledFunction(mi, scope, hasDynamicScope, breakpoint, mi.isInstanceInitializer);
        }
        mi.freeMethod.methodInfo = mi;
        if (hasDynamicScope) {
          return Shumway.AVM2.Runtime.bindFreeMethodScope(mi, scope);
        }
        return mi.freeMethod;
      }
      Runtime.createFunction = createFunction;
      function ensureFunctionIsInitialized(methodInfo) {
        var mi = methodInfo;
        if (!mi.analysis) {
          mi.analysis = new Analysis(mi);
          if (mi.needsActivation()) {
            mi.activationPrototype = new ActivationInfo(mi);
            new Shumway.AVM2.Runtime.ActivationBindings(mi).applyTo(mi.abc.applicationDomain, mi.activationPrototype);
          }
          var exceptions = mi.exceptions;
          for (var i = 0, j = exceptions.length; i < j; i++) {
            var handler = exceptions[i];
            if (handler.varName) {
              var varTrait = Object.create(Trait.prototype);
              varTrait.kind = 0;
              varTrait.name = handler.varName;
              varTrait.typeName = handler.typeName;
              varTrait.holder = mi;
              handler.scopeObject = new CatchScopeObject(mi.abc.applicationDomain, varTrait);
            } else {
              handler.scopeObject = new CatchScopeObject(undefined, undefined);
            }
          }
        }
      }
      Runtime.ensureFunctionIsInitialized = ensureFunctionIsInitialized;
      function getTraitFunction(trait, scope, natives) {
        true;
        true;
        var mi = trait.methodInfo;
        var fn;
        if (mi.isNative()) {
          var md = trait.metadata;
          if (md && md.native) {
            var nativeName = md.native.value[0].value;
            var makeNativeFunction = getNative(nativeName);
            fn = makeNativeFunction && makeNativeFunction(null, scope);
          } else if (md && md.unsafeJSNative) {
            fn = getNative(md.unsafeJSNative.value[0].value);
          } else if (natives) {
            var k = Multiname.getName(mi.name);
            if (trait.isGetter()) {
              fn = natives[k] ? natives[k].get : undefined;
            } else if (trait.isSetter()) {
              fn = natives[k] ? natives[k].set : undefined;
            } else {
              fn = natives[k];
            }
          }
          if (!fn) {
            Shumway.Debug.warning('No native method for: ' + trait.kindName() + ' ' + mi.holder.name + '::' + Multiname.getQualifiedName(mi.name));
            return function (mi) {
              return function () {
                Shumway.Debug.warning('Calling undefined native method: ' + trait.kindName() + ' ' + mi.holder.name + '::' + Multiname.getQualifiedName(mi.name));
              };
            }(mi);
          }
        } else {
          if (Runtime.traceExecution.value >= 2) {
            log('Creating Function For Trait: ' + trait.holder + ' ' + trait);
          }
          fn = createFunction(mi, scope, false, false);
          true;
        }
        if (Runtime.traceExecution.value >= 3) {
          log('Made Function: ' + Multiname.getQualifiedName(mi.name));
        }
        return fn;
      }
      Runtime.getTraitFunction = getTraitFunction;
      function createClass(classInfo, baseClass, scope) {
        true;
        var ci = classInfo;
        var ii = ci.instanceInfo;
        var domain = ci.abc.applicationDomain;
        var className = Multiname.getName(ii.name);
        if (Runtime.traceExecution.value) {
          log('Creating ' + (ii.isInterface() ? 'Interface' : 'Class') + ': ' + className + (ci.native ? ' replaced with native ' + ci.native.cls : ''));
        }
        var cls;
        if (ii.isInterface()) {
          cls = Shumway.AVM2.Runtime.Interface.createInterface(classInfo);
        } else {
          cls = Shumway.AVM2.Runtime.Class.createClass(classInfo, baseClass, scope);
        }
        if (Runtime.traceClasses.value) {
          domain.loadedClasses.push(cls);
          domain.traceLoadedClasses(true);
        }
        if (ii.isInterface()) {
          return cls;
        }
        domain.onMessage.notify1('classCreated', cls);
        if (cls.instanceConstructor && cls !== Shumway.AVM2.Runtime.Class) {
          cls.verify();
        }
        if (baseClass && (Multiname.getQualifiedName(baseClass.classInfo.instanceInfo.name.name) === 'Proxy' || baseClass.isProxy)) {
          installProxyClassWrapper(cls);
          cls.isProxy = true;
        }
        classInfo.classObject = cls;
        createFunction(classInfo.init, scope, false, false).call(cls);
        if (Runtime.sealConstTraits) {
          this.sealConstantTraits(cls, ci.traits);
        }
        return cls;
      }
      Runtime.createClass = createClass;
      function sealConstantTraits(object, traits) {
        for (var i = 0, j = traits.length; i < j; i++) {
          var trait = traits[i];
          if (trait.isConst()) {
            var qn = Multiname.getQualifiedName(trait.name);
            var value = object[qn];
            (function (qn, value) {
              Object.defineProperty(object, qn, {
                configurable: false,
                enumerable: false,
                get: function () {
                  return value;
                },
                set: function () {
                  throwErrorFromVM(Shumway.AVM2.Runtime.AVM2.currentDomain(), 'ReferenceError', 'Illegal write to read-only property ' + qn + '.', 0);
                }
              });
            }(qn, value));
          }
        }
      }
      Runtime.sealConstantTraits = sealConstantTraits;
      function applyType(domain, factory, types) {
        var factoryClassName = factory.classInfo.instanceInfo.name.name;
        if (factoryClassName === 'Vector') {
          true;
          var type = types[0];
          var typeClassName;
          if (!Shumway.isNullOrUndefined(type)) {
            typeClassName = type.classInfo.instanceInfo.name.name.toLowerCase();
            switch (typeClassName) {
            case 'int':
            case 'uint':
            case 'double':
            case 'object':
              return domain.getClass('packageInternal __AS3__.vec.Vector$' + typeClassName);
            }
          }
          return domain.getClass('packageInternal __AS3__.vec.Vector$object').applyType(type);
        } else {
          return Shumway.Debug.notImplemented(factoryClassName);
        }
      }
      Runtime.applyType = applyType;
    }(AVM2.Runtime || (AVM2.Runtime = {})));
    var Runtime = AVM2.Runtime;
  }(Shumway.AVM2 || (Shumway.AVM2 = {})));
  var AVM2 = Shumway.AVM2;
}(Shumway || (Shumway = {})));
var CC = Shumway.AVM2.Runtime.CODE_CACHE;
var VM_LENGTH = Shumway.AVM2.Runtime.VM_LENGTH;
var VM_IS_PROXY = Shumway.AVM2.Runtime.VM_IS_PROXY;
var VM_CALL_PROXY = Shumway.AVM2.Runtime.VM_CALL_PROXY;
var VM_NATIVE_BUILTIN_ORIGINALS = Shumway.AVM2.Runtime.VM_NATIVE_BUILTIN_ORIGINALS;
var VM_OPEN_METHOD_PREFIX = 'm';
var VM_OPEN_SET_METHOD_PREFIX = 's';
var VM_OPEN_GET_METHOD_PREFIX = 'g';
var SAVED_SCOPE_NAME = '$SS';
var originalStringReplace = String.prototype.replace;
XRegExp.install({
  natives: true
});
var callWriter = new IndentingWriter(false, function (str) {
    print(str);
  });
var objectIDs = 0;
var OBJECT_NAME = 'Object Name';
function objectConstantName(object) {
  true;
  if (object.hasOwnProperty(OBJECT_NAME)) {
    return object[OBJECT_NAME];
  }
  if (object instanceof LazyInitializer) {
    return object.getName();
  }
  var name, id = objectIDs++;
  if (object instanceof Global) {
    name = '$G' + id;
  } else if (object instanceof Multiname) {
    name = '$M' + id;
  } else if (isClass(object)) {
    name = '$C' + id;
  } else {
    name = '$O' + id;
  }
  Object.defineProperty(object, OBJECT_NAME, {
    value: name,
    writable: false,
    enumerable: false
  });
  jsGlobal[name] = object;
  return name;
}
var isClass = Shumway.AVM2.Runtime.isClass;
var isTrampoline = Shumway.AVM2.Runtime.isTrampoline;
var isMemoizer = Shumway.AVM2.Runtime.isMemoizer;
var LazyInitializer = Shumway.AVM2.Runtime.LazyInitializer;
var getNamespaceResolutionMap = Shumway.AVM2.Runtime.getNamespaceResolutionMap;
var resolveMultinameProperty = Shumway.AVM2.Runtime.resolveMultinameProperty;
var asGetPublicProperty = Shumway.AVM2.Runtime.asGetPublicProperty;
var asGetProperty = Shumway.AVM2.Runtime.asGetProperty;
var asGetPropertyLikelyNumeric = Shumway.AVM2.Runtime.asGetPropertyLikelyNumeric;
var asGetResolvedStringProperty = Shumway.AVM2.Runtime.asGetResolvedStringProperty;
var asCallResolvedStringProperty = Shumway.AVM2.Runtime.asCallResolvedStringProperty;
var asGetResolvedStringPropertyFallback = Shumway.AVM2.Runtime.asGetResolvedStringPropertyFallback;
var asSetPublicProperty = Shumway.AVM2.Runtime.asSetPublicProperty;
var asSetProperty = Shumway.AVM2.Runtime.asSetProperty;
var asSetPropertyLikelyNumeric = Shumway.AVM2.Runtime.asSetPropertyLikelyNumeric;
var asDefinePublicProperty = Shumway.AVM2.Runtime.asDefinePublicProperty;
var asDefineProperty = Shumway.AVM2.Runtime.asDefineProperty;
var asCallPublicProperty = Shumway.AVM2.Runtime.asCallPublicProperty;
var asCallProperty = Shumway.AVM2.Runtime.asCallProperty;
var asCallSuper = Shumway.AVM2.Runtime.asCallSuper;
var asSetSuper = Shumway.AVM2.Runtime.asSetSuper;
var asGetSuper = Shumway.AVM2.Runtime.asGetSuper;
var construct = Shumway.AVM2.Runtime.construct;
var asConstructProperty = Shumway.AVM2.Runtime.asConstructProperty;
var asHasProperty = Shumway.AVM2.Runtime.asHasProperty;
var asDeleteProperty = Shumway.AVM2.Runtime.asDeleteProperty;
var asGetNumericProperty = Shumway.AVM2.Runtime.asGetNumericProperty;
var asSetNumericProperty = Shumway.AVM2.Runtime.asSetNumericProperty;
var asGetDescendants = Shumway.AVM2.Runtime.asGetDescendants;
var asNextNameIndex = Shumway.AVM2.Runtime.asNextNameIndex;
var asNextName = Shumway.AVM2.Runtime.asNextName;
var asNextValue = Shumway.AVM2.Runtime.asNextValue;
var asGetEnumerableKeys = Shumway.AVM2.Runtime.asGetEnumerableKeys;
var initializeGlobalObject = Shumway.AVM2.Runtime.initializeGlobalObject;
initializeGlobalObject(jsGlobal);
var asTypeOf = Shumway.AVM2.Runtime.asTypeOf;
var publicizeProperties = Shumway.AVM2.Runtime.publicizeProperties;
var asGetSlot = Shumway.AVM2.Runtime.asGetSlot;
var asSetSlot = Shumway.AVM2.Runtime.asSetSlot;
var asHasNext2 = Shumway.AVM2.Runtime.asHasNext2;
var getDescendants = Shumway.AVM2.Runtime.getDescendants;
var checkFilter = Shumway.AVM2.Runtime.checkFilter;
var ActivationInfo = Shumway.AVM2.Runtime.ActivationInfo;
var ScopeStack = Shumway.AVM2.Runtime.ScopeStack;
var Scope = Shumway.AVM2.Runtime.Scope;
var bindFreeMethodScope = Shumway.AVM2.Runtime.bindFreeMethodScope;
var nameInTraits = Shumway.AVM2.Runtime.nameInTraits;
function resolveMultiname(object, mn, traitsOnly) {
  return object.resolveMultinameProperty(mn.namespaces, mn.name, mn.flags);
}
var sliceArguments = Shumway.AVM2.Runtime.sliceArguments;
var nonProxyingHasProperty = Shumway.AVM2.Runtime.nonProxyingHasProperty;
var forEachPublicProperty = Shumway.AVM2.Runtime.forEachPublicProperty;
var wrapJSObject = Shumway.AVM2.Runtime.wrapJSObject;
var asCreateActivation = Shumway.AVM2.Runtime.asCreateActivation;
var CatchScopeObject = Shumway.AVM2.Runtime.CatchScopeObject;
var Global = Shumway.AVM2.Runtime.Global;
var canCompile = Shumway.AVM2.Runtime.canCompile;
var shouldCompile = Shumway.AVM2.Runtime.shouldCompile;
var forceCompile = Shumway.AVM2.Runtime.forceCompile;
var createInterpretedFunction = Shumway.AVM2.Runtime.createInterpretedFunction;
var debugName = Shumway.AVM2.Runtime.debugName;
var createCompiledFunction = Shumway.AVM2.Runtime.createCompiledFunction;
var getMethodOverrideKey = Shumway.AVM2.Runtime.getMethodOverrideKey;
var checkMethodOverrides = Shumway.AVM2.Runtime.checkMethodOverrides;
var makeTrampoline = Shumway.AVM2.Runtime.makeTrampoline;
var makeMemoizer = Shumway.AVM2.Runtime.makeMemoizer;
var createFunction = Shumway.AVM2.Runtime.createFunction;
var ensureFunctionIsInitialized = Shumway.AVM2.Runtime.ensureFunctionIsInitialized;
var getTraitFunction = Shumway.AVM2.Runtime.getTraitFunction;
var createClass = Shumway.AVM2.Runtime.createClass;
var sealConstantTraits = Shumway.AVM2.Runtime.sealConstantTraits;
var applyType = Shumway.AVM2.Runtime.applyType;
var throwError = Shumway.AVM2.Runtime.throwError;
var throwErrorFromVM = Shumway.AVM2.Runtime.throwErrorFromVM;
var translateError = Shumway.AVM2.Runtime.translateError;
var asIsInstanceOf = Shumway.AVM2.Runtime.asIsInstanceOf;
var asIsType = Shumway.AVM2.Runtime.asIsType;
var asAsType = Shumway.AVM2.Runtime.asAsType;
var asCoerceByMultiname = Shumway.AVM2.Runtime.asCoerceByMultiname;
var asCoerce = Shumway.AVM2.Runtime.asCoerce;
var asCoerceString = Shumway.AVM2.Runtime.asCoerceString;
var asCoerceInt = Shumway.AVM2.Runtime.asCoerceInt;
var asCoerceUint = Shumway.AVM2.Runtime.asCoerceUint;
var asCoerceNumber = Shumway.AVM2.Runtime.asCoerceNumber;
var asCoerceBoolean = Shumway.AVM2.Runtime.asCoerceBoolean;
var asCoerceObject = Shumway.AVM2.Runtime.asCoerceObject;
var asDefaultCompareFunction = Shumway.AVM2.Runtime.asDefaultCompareFunction;
var asCompare = Shumway.AVM2.Runtime.asCompare;
var asAdd = Shumway.AVM2.Runtime.asAdd;
var GlobalMultinameResolver = Shumway.AVM2.Runtime.GlobalMultinameResolver;
var Shumway;
(function (Shumway) {
  (function (AVM2) {
    (function (Runtime) {
      Shumway.AVM2.Runtime.VM_METHOD_OVERRIDES['static mochi.as3.MochiServices::connect'] = function () {
        return;
      };
      Shumway.AVM2.Runtime.VM_METHOD_OVERRIDES['static MochiBot::track'] = function () {
        return;
      };
      Shumway.AVM2.Runtime.VM_METHOD_OVERRIDES['com.midasplayer.debug.DebugLog::trace'] = function (msg) {
        log(msg);
      };
      Shumway.AVM2.Runtime.VM_METHOD_OVERRIDES['com.midasplayer.engine.comm.DebugGameComm::getGameData'] = function () {
        return '<gamedata randomseed="554884453" version="1">\n<musicOn>true</musicOn>\n<soundOn>true</soundOn>\n<isShortGame>false</isShortGame>\n<booster_1>0</booster_1>\n<booster_2>0</booster_2>\n<booster_3>0</booster_3>\n<booster_4>0</booster_4>\n<booster_5>0</booster_5>\n<bestScore>0</bestScore>\n<bestChain>0</bestChain>\n<bestLevel>0</bestLevel>\n<bestCrushed>0</bestCrushed>\n<bestMixed>0</bestMixed>\n<text id="outro.crushed">Candy crushed</text>\n<text id="outro.bestever">best ever</text>\n<text id="outro.trophy.two">scored {0} in one game</text>\n<text id="outro.combo_color_color">All Clear Created</text>\n<text id="outro.trophy.one">crushed {0} candy in one game</text>\n<text id="outro.score">Score</text>\n<text id="outro.opengame">Please register to play the full game</text>\n<text id="outro.chain">Longest chain</text>\n<text id="outro.time">Game ends in {0} seconds</text>\n<text id="outro.combo_color_line">Super Stripes Created</text>\n<text id="game.nomoves">No more moves!</text>\n<text id="outro.combo_wrapper_line">Mega-Candy Created</text>\n<text id="intro.time">Game starts in {0} seconds</text>\n<text id="outro.now">now</text>\n<text id="outro.level">Level reached</text>\n<text id="outro.title">Game Over</text>\n<text id="intro.info1">Match 3 Candy of the same colour to crush them. Matching 4 or 5 in different formations generates special sweets that are extra tasty.</text>\n<text id="intro.info2">You can also combine the special sweets for additional effects by switching them with each other. Try these combinations for a taste you will not forget: </text>\n<text id="outro.combo_color_wrapper">Double Colour Bombs Created</text>\n<text id="outro.trophy.three">made {0} combined candy in one game</text>\n<text id="intro.title">Play like this:</text>\n</gamedata>';
      };
      Shumway.AVM2.Runtime.VM_METHOD_OVERRIDES['com.antkarlov.Preloader::com.antkarlov:Preloader.isUrl'] = function () {
        return true;
      };
      Shumway.AVM2.Runtime.VM_METHOD_OVERRIDES['static com.demonsters.debugger.MonsterDebugger::initialize'] = function () {
      };
      Shumway.AVM2.Runtime.VM_METHOD_OVERRIDES['com.spilgames.api.core.tracking.TrackConfig::getTrackers'] = function () {
        return [];
      };
      Shumway.AVM2.Runtime.VM_METHOD_OVERRIDES['com.spilgames.api.components.TextFields.AutoFitTextFieldEx::com.spilgames.api.components.TextFields:AutoFitTextFieldEx.updateProperties'] = Shumway.AVM2.Runtime.VM_METHOD_OVERRIDES['com.spilgames.api.components.TextFields.AutoFitTextFieldEx::com.spilgames.api.components.TextFields:AutoFitTextFieldEx.updateTextSize'] = function () {
      };
    }(AVM2.Runtime || (AVM2.Runtime = {})));
    var Runtime = AVM2.Runtime;
  }(Shumway.AVM2 || (Shumway.AVM2 = {})));
  var AVM2 = Shumway.AVM2;
}(Shumway || (Shumway = {})));
var checkArguments = true;
function asCheckVectorSetNumericProperty(i, length, fixed) {
  if (i < 0 || i > length || i === length && fixed || !isNumeric(i)) {
    throwError('RangeError', Errors.OutOfRangeError, i, length);
  }
}
function asCheckVectorGetNumericProperty(i, length) {
  if (i < 0 || i >= length || !isNumeric(i)) {
    throwError('RangeError', Errors.OutOfRangeError, i, length);
  }
}
var TypedArrayVector = function () {
    var EXTRA_CAPACITY = 4;
    var INITIAL_CAPACITY = 10;
    var DEFAULT_VALUE = 0;
    function vector(length, fixed) {
      length = length | 0;
      this._fixed = !(!fixed);
      this._buffer = new Int32Array(Math.max(INITIAL_CAPACITY, length + EXTRA_CAPACITY));
      this._offset = 0;
      this._length = length;
    }
    vector.callable = function (object) {
      if (object instanceof vector) {
        return object;
      }
      var length = object.asGetProperty(undefined, 'length');
      if (length !== undefined) {
        var v = new vector(length, false);
        for (var i = 0; i < length; i++) {
          v.asSetNumericProperty(i, object.asGetPublicProperty(i));
        }
        return v;
      }
      unexpected();
    };
    vector.prototype.internalToString = function () {
      var str = '';
      var start = this._offset;
      var end = start + this._length;
      for (var i = 0; i < this._buffer.length; i++) {
        if (i === start) {
          str += '[';
        }
        if (i === end) {
          str += ']';
        }
        str += this._buffer[i];
        if (i < this._buffer.length - 1) {
          str += ',';
        }
      }
      if (this._offset + this._length === this._buffer.length) {
        str += ']';
      }
      return str + ': offset: ' + this._offset + ', length: ' + this._length + ', capacity: ' + this._buffer.length;
    };
    vector.prototype.toString = function () {
      var str = '';
      for (var i = 0; i < this._length; i++) {
        str += this._buffer[this._offset + i];
        if (i < this._length - 1) {
          str += ',';
        }
      }
      return str;
    };
    vector.prototype._view = function () {
      return this._buffer.subarray(this._offset, this._offset + this._length);
    };
    vector.prototype._ensureCapacity = function (length) {
      var minCapacity = this._offset + length;
      if (minCapacity < this._buffer.length) {
        return;
      }
      if (length <= this._buffer.length) {
        var offset = this._buffer.length - length >> 2;
        this._buffer.set(this._view(), offset);
        this._offset = offset;
        return;
      }
      var oldCapacity = this._buffer.length;
      var newCapacity = oldCapacity * 3 >> 2;
      if (newCapacity < minCapacity) {
        newCapacity = minCapacity;
      }
      var buffer = new Int32Array(newCapacity);
      buffer.set(this._buffer, 0);
      this._buffer = buffer;
    };
    vector.prototype.concat = function () {
      notImplemented('TypedArrayVector.concat');
    };
    vector.prototype.every = function (callback, thisObject) {
      for (var i = 0; i < this._length; i++) {
        if (!callback.call(thisObject, this.asGetNumericProperty(i), i, this)) {
          return false;
        }
      }
      return true;
    };
    vector.prototype.filter = function (callback, thisObject) {
      var v = new vector();
      for (var i = 0; i < this._length; i++) {
        if (callback.call(thisObject, this.asGetNumericProperty(i), i, this)) {
          v.push(this.asGetNumericProperty(i));
        }
      }
      return v;
    };
    vector.prototype.some = function (callback, thisObject) {
      if (arguments.length !== 2) {
        throwError('ArgumentError', Errors.WrongArgumentCountError);
      } else if (!isFunction(callback)) {
        throwError('ArgumentError', Errors.CheckTypeFailedError);
      }
      for (var i = 0; i < this._length; i++) {
        if (callback.call(thisObject, this.asGetNumericProperty(i), i, this)) {
          return true;
        }
      }
      return false;
    };
    vector.prototype.forEach = function (callback, thisObject) {
      for (var i = 0; i < this._length; i++) {
        callback.call(thisObject, this.asGetNumericProperty(i), i, this);
      }
    };
    vector.prototype.join = function (sep) {
      notImplemented('TypedArrayVector.join');
    };
    vector.prototype.indexOf = function (searchElement, fromIndex) {
      notImplemented('TypedArrayVector.indexOf');
    };
    vector.prototype.lastIndexOf = function (searchElement, fromIndex) {
      notImplemented('TypedArrayVector.lastIndexOf');
    };
    vector.prototype.map = function (callback, thisObject) {
      if (!isFunction(callback)) {
        throwError('ArgumentError', Errors.CheckTypeFailedError);
      }
      var v = new vector();
      for (var i = 0; i < this._length; i++) {
        v.push(callback.call(thisObject, this.asGetNumericProperty(i), i, this));
      }
      return v;
    };
    vector.prototype.push = function () {
      this._checkFixed();
      this._ensureCapacity(this._length + arguments.length);
      for (var i = 0; i < arguments.length; i++) {
        this._buffer[this._offset + this._length++] = arguments[i];
      }
    };
    vector.prototype.pop = function () {
      this._checkFixed();
      if (this._length === 0) {
        return DEFAULT_VALUE;
      }
      this._length--;
      return this._buffer[this._offset + this._length];
    };
    vector.prototype.reverse = function () {
      var l = this._offset;
      var r = this._offset + this._length - 1;
      var b = this._buffer;
      while (l < r) {
        var t = b[l];
        b[l] = b[r];
        b[r] = t;
        l++;
        r--;
      }
    };
    vector.CASEINSENSITIVE = 1;
    vector.DESCENDING = 2;
    vector.UNIQUESORT = 4;
    vector.RETURNINDEXEDARRAY = 8;
    vector.NUMERIC = 16;
    function defaultCompareFunction(a, b) {
      return String(a).localeCompare(String(b));
    }
    function compare(a, b, options, compareFunction) {
      assertNotImplemented(!(options & vector.CASEINSENSITIVE), 'CASEINSENSITIVE');
      assertNotImplemented(!(options & vector.UNIQUESORT), 'UNIQUESORT');
      assertNotImplemented(!(options & vector.RETURNINDEXEDARRAY), 'RETURNINDEXEDARRAY');
      var result = 0;
      if (!compareFunction) {
        compareFunction = defaultCompareFunction;
      }
      if (options & vector.NUMERIC) {
        a = toNumber(a);
        b = toNumber(b);
        result = a < b ? -1 : a > b ? 1 : 0;
      } else {
        result = compareFunction(a, b);
      }
      if (options & vector.DESCENDING) {
        result *= -1;
      }
      return result;
    }
    function _sort(a) {
      var stack = [];
      var sp = -1;
      var l = 0;
      var r = a.length - 1;
      var i, j, swap, temp;
      while (true) {
        if (r - l <= 100) {
          for (j = l + 1; j <= r; j++) {
            swap = a[j];
            i = j - 1;
            while (i >= l && a[i] > swap) {
              a[i + 1] = a[i--];
            }
            a[i + 1] = swap;
          }
          if (sp == -1) {
            break;
          }
          r = stack[sp--];
          l = stack[sp--];
        } else {
          var median = l + r >> 1;
          i = l + 1;
          j = r;
          swap = a[median];
          a[median] = a[i];
          a[i] = swap;
          if (a[l] > a[r]) {
            swap = a[l];
            a[l] = a[r];
            a[r] = swap;
          }
          if (a[i] > a[r]) {
            swap = a[i];
            a[i] = a[r];
            a[r] = swap;
          }
          if (a[l] > a[i]) {
            swap = a[l];
            a[l] = a[i];
            a[i] = swap;
          }
          temp = a[i];
          while (true) {
            do {
              i++;
            } while (a[i] < temp);
            do {
              j--;
            } while (a[j] > temp);
            if (j < i) {
              break;
            }
            swap = a[i];
            a[i] = a[j];
            a[j] = swap;
          }
          a[l + 1] = a[j];
          a[j] = temp;
          if (r - i + 1 >= j - l) {
            stack[++sp] = i;
            stack[++sp] = r;
            r = j - 1;
          } else {
            stack[++sp] = l;
            stack[++sp] = j - 1;
            l = i;
          }
        }
      }
      return a;
    }
    vector.prototype._sortNumeric = function (descending) {
      _sort(this._view());
      if (descending) {
        this.reverse();
      }
    };
    vector.prototype.sort = function () {
      if (arguments.length === 0) {
        return Array.prototype.sort.call(this._view());
      }
      var compareFunction, options = 0;
      if (arguments[0] instanceof Function) {
        compareFunction = arguments[0];
      } else if (isNumber(arguments[0])) {
        options = arguments[0];
      }
      if (isNumber(arguments[1])) {
        options = arguments[1];
      }
      if (options & TypedArrayVector.NUMERIC) {
        return this._sortNumeric(options & vector.DESCENDING);
      }
      Array.prototype.sort.call(this._view(), function (a, b) {
        return compare(a, b, options, compareFunction);
      });
    };
    vector.prototype.asGetNumericProperty = function (i) {
      checkArguments && asCheckVectorGetNumericProperty(i, this._length);
      return this._buffer[this._offset + i];
    };
    vector.prototype.asSetNumericProperty = function (i, v) {
      checkArguments && asCheckVectorSetNumericProperty(i, this._length, this._fixed);
      if (i === this._length) {
        this._ensureCapacity(this._length + 1);
        this._length++;
      }
      this._buffer[this._offset + i] = v;
    };
    vector.prototype.shift = function () {
      this._checkFixed();
      if (this._length === 0) {
        return 0;
      }
      this._length--;
      return this._buffer[this._offset++];
    };
    vector.prototype._checkFixed = function () {
      if (this._fixed) {
        throwError('RangeError', Errors.VectorFixedError);
      }
    };
    vector.prototype._slide = function (distance) {
      this._buffer.set(this._view(), this._offset + distance);
      this._offset += distance;
    };
    vector.prototype.unshift = function () {
      this._checkFixed();
      if (!arguments.length) {
        return;
      }
      this._ensureCapacity(this._length + arguments.length);
      this._slide(arguments.length);
      this._offset -= arguments.length;
      this._length += arguments.length;
      for (var i = 0; i < arguments.length; i++) {
        this._buffer[this._offset + i] = arguments[i];
      }
    };
    vector.prototype.asGetEnumerableKeys = function () {
      if (vector.prototype === this) {
        return Object.prototype.asGetEnumerableKeys.call(this);
      }
      var keys = [];
      for (var i = 0; i < this._length; i++) {
        keys.push(i);
      }
      return keys;
    };
    vector.prototype.asHasProperty = function (namespaces, name, flags) {
      if (vector.prototype === this || !isNumeric(name)) {
        return Object.prototype.asHasProperty.call(this, namespaces, name, flags);
      }
      var index = toNumber(name);
      return index >= 0 && index < this._length;
    };
    Object.defineProperty(vector.prototype, 'length', {
      get: function () {
        return this._length;
      },
      set: function (length) {
        length = length >>> 0;
        if (length > this._length) {
          this._ensureCapacity(length);
          for (var i = this._offset + this._length, j = this._offset + length; i < j; i++) {
            this._buffer[i] = DEFAULT_VALUE;
          }
        }
        this._length = length;
      }
    });
    vector.prototype._spliceHelper = function (index, insertCount, deleteCount, args, offset) {
      insertCount = clamp(insertCount, 0, args.length - offset);
      deleteCount = clamp(deleteCount, 0, this._length - index);
      this._ensureCapacity(this._length - deleteCount + insertCount);
      var right = this._offset + index + deleteCount;
      var slice = this._buffer.subarray(right, right + this._length - index - deleteCount);
      this._buffer.set(slice, this._offset + index + insertCount);
      this._length += insertCount - deleteCount;
      for (var i = 0; i < insertCount; i++) {
        this._buffer[this._offset + index + i] = args.asGetNumericProperty(offset + i);
      }
    };
    vector.prototype.asGetEnumerableKeys = function () {
      if (vector.prototype === this) {
        return Object.prototype.asGetEnumerableKeys.call(this);
      }
      var keys = [];
      for (var i = 0; i < this._length; i++) {
        keys.push(i);
      }
      return keys;
    };
    return vector;
  }();
var typedArrayVectorTemplate = 'var EXTRA_CAPACITY=4,INITIAL_CAPACITY=10,DEFAULT_VALUE=0;function vector(a,b){a|=0;this._fixed=!!b;this._buffer=new Int32Array(Math.max(INITIAL_CAPACITY,a+EXTRA_CAPACITY));this._offset=0;this._length=a}vector.callable=function(a){if(a instanceof vector)return a;var b=a.asGetProperty(void 0,"length");if(void 0!==b){for(var c=new vector(b,!1),d=0;d<b;d++)c.asSetNumericProperty(d,a.asGetPublicProperty(d));return c}unexpected()}; vector.prototype.internalToString=function(){for(var a="",b=this._offset,c=b+this._length,d=0;d<this._buffer.length;d++)d===b&&(a+="["),d===c&&(a+="]"),a+=this._buffer[d],d<this._buffer.length-1&&(a+=",");this._offset+this._length===this._buffer.length&&(a+="]");return a+": offset: "+this._offset+", length: "+this._length+", capacity: "+this._buffer.length};vector.prototype.toString=function(){for(var a="",b=0;b<this._length;b++)a+=this._buffer[this._offset+b],b<this._length-1&&(a+=",");return a}; vector.prototype._view=function(){return this._buffer.subarray(this._offset,this._offset+this._length)};vector.prototype._ensureCapacity=function(a){var b=this._offset+a;b<this._buffer.length||(a<=this._buffer.length?(b=this._buffer.length-a>>2,this._buffer.set(this._view(),b),this._offset=b):(a=3*this._buffer.length>>2,a<b&&(a=b),b=new Int32Array(a),b.set(this._buffer,0),this._buffer=b))}; vector.prototype.every=function(a,b){for(var c=0;c<this._length;c++)if(!a.call(b,this.asGetNumericProperty(c),c,this))return!1;return!0};vector.prototype.filter=function(a,b){for(var c=new vector,d=0;d<this._length;d++)a.call(b,this.asGetNumericProperty(d),d,this)&&c.push(this.asGetNumericProperty(d));return c}; vector.prototype.some=function(a,b){2!==arguments.length?throwError("ArgumentError",Errors.WrongArgumentCountError):isFunction(a)||throwError("ArgumentError",Errors.CheckTypeFailedError);for(var c=0;c<this._length;c++)if(a.call(b,this.asGetNumericProperty(c),c,this))return!0;return!1};vector.prototype.forEach=function(a,b){for(var c=0;c<this._length;c++)a.call(b,this.asGetNumericProperty(c),c,this)};vector.prototype.join=function(a){notImplemented("TypedArrayVector.join")}; vector.prototype.indexOf=function(a,b){notImplemented("TypedArrayVector.indexOf")};vector.prototype.lastIndexOf=function(a,b){notImplemented("TypedArrayVector.lastIndexOf")};vector.prototype.map=function(a,b){isFunction(a)||throwError("ArgumentError",Errors.CheckTypeFailedError);for(var c=new vector,d=0;d<this._length;d++)c.push(a.call(b,this.asGetNumericProperty(d),d,this));return c}; vector.prototype.push=function(){this._checkFixed();this._ensureCapacity(this._length+arguments.length);for(var a=0;a<arguments.length;a++)this._buffer[this._offset+this._length++]=arguments[a]};vector.prototype.pop=function(){this._checkFixed();if(0===this._length)return DEFAULT_VALUE;this._length--;return this._buffer[this._offset+this._length]};vector.prototype.reverse=function(){for(var a=this._offset,b=this._offset+this._length-1,c=this._buffer;a<b;){var d=c[a];c[a]=c[b];c[b]=d;a++;b--}}; vector.CASEINSENSITIVE=1;vector.DESCENDING=2;vector.UNIQUESORT=4;vector.RETURNINDEXEDARRAY=8;vector.NUMERIC=16;function defaultCompareFunction(a,b){return String(a).localeCompare(String(b))} function compare(a,b,c,d){assertNotImplemented(!(c&vector.CASEINSENSITIVE),"CASEINSENSITIVE");assertNotImplemented(!(c&vector.UNIQUESORT),"UNIQUESORT");assertNotImplemented(!(c&vector.RETURNINDEXEDARRAY),"RETURNINDEXEDARRAY");var f=0;d||(d=defaultCompareFunction);c&vector.NUMERIC?(a=toNumber(a),b=toNumber(b),f=a<b?-1:a>b?1:0):f=d(a,b);c&vector.DESCENDING&&(f*=-1);return f} function _sort(a){for(var b=[],c=-1,d=0,f=a.length-1,e,g,h,k;;)if(100>=f-d){for(g=d+1;g<=f;g++){h=a[g];for(e=g-1;e>=d&&a[e]>h;)a[e+1]=a[e--];a[e+1]=h}if(-1==c)break;f=b[c--];d=b[c--]}else{k=d+f>>1;e=d+1;g=f;h=a[k];a[k]=a[e];a[e]=h;a[d]>a[f]&&(h=a[d],a[d]=a[f],a[f]=h);a[e]>a[f]&&(h=a[e],a[e]=a[f],a[f]=h);a[d]>a[e]&&(h=a[d],a[d]=a[e],a[e]=h);for(k=a[e];;){do e++;while(a[e]<k);do g--;while(a[g]>k);if(g<e)break;h=a[e];a[e]=a[g];a[g]=h}a[d+1]=a[g];a[g]=k;f-e+1>=g-d?(b[++c]=e,b[++c]=f,f=g-1):(b[++c]=d, b[++c]=g-1,d=e)}return a}vector.prototype._sortNumeric=function(a){_sort(this._view());a&&this.reverse()};vector.prototype.sort=function(){if(0===arguments.length)return Array.prototype.sort.call(this._view());var a,b=0;arguments[0]instanceof Function?a=arguments[0]:isNumber(arguments[0])&&(b=arguments[0]);isNumber(arguments[1])&&(b=arguments[1]);if(b&TypedArrayVector.NUMERIC)return this._sortNumeric(b&vector.DESCENDING);Array.prototype.sort.call(this._view(),function(c,d){return compare(c,d,b,a)})}; vector.prototype.asGetNumericProperty=function(a){checkArguments&&asCheckVectorGetNumericProperty(a,this._length);return this._buffer[this._offset+a]};vector.prototype.asSetNumericProperty=function(a,b){checkArguments&&asCheckVectorSetNumericProperty(a,this._length,this._fixed);a===this._length&&(this._ensureCapacity(this._length+1),this._length++);this._buffer[this._offset+a]=b};vector.prototype.shift=function(){this._checkFixed();if(0===this._length)return 0;this._length--;return this._buffer[this._offset++]}; vector.prototype._checkFixed=function(){this._fixed&&throwError("RangeError",Errors.VectorFixedError)};vector.prototype._slide=function(a){this._buffer.set(this._view(),this._offset+a);this._offset+=a};vector.prototype.unshift=function(){this._checkFixed();if(arguments.length){this._ensureCapacity(this._length+arguments.length);this._slide(arguments.length);this._offset-=arguments.length;this._length+=arguments.length;for(var a=0;a<arguments.length;a++)this._buffer[this._offset+a]=arguments[a]}}; vector.prototype.asGetEnumerableKeys=function(){if(vector.prototype===this)return Object.prototype.asGetEnumerableKeys.call(this);for(var a=[],b=0;b<this._length;b++)a.push(b);return a};vector.prototype.asHasProperty=function(a,b,c){if(vector.prototype===this||!isNumeric(b))return Object.prototype.asHasProperty.call(this,a,b,c);a=toNumber(b);return 0<=a&&a<this._length}; Object.defineProperty(vector.prototype,"length",{get:function(){return this._length},set:function(a){a>>>=0;if(a>this._length){this._ensureCapacity(a);for(var b=this._offset+this._length,c=this._offset+a;b<c;b++)this._buffer[b]=DEFAULT_VALUE}this._length=a}}); vector.prototype._spliceHelper=function(a,b,c,d,f){debugger;b=clamp(b,0,d.length-f);c=clamp(c,0,this._length-a);this._ensureCapacity(this._length-c+b);var e=this._offset+a+c,e=this._buffer.subarray(e,e+this._length-a-c);this._buffer.set(e,this._offset+a+b);this._length+=b-c;for(c=0;c<b;c++)this._buffer[this._offset+a+c]=d.asGetNumericProperty(f+c)}; vector.prototype.asGetEnumerableKeys=function(){if(vector.prototype===this)return Object.prototype.asGetEnumerableKeys.call(this);for(var a=[],b=0;b<this._length;b++)a.push(b);return a};';
var Int32Vector = TypedArrayVector;
var Uint32Vector = new Function(originalStringReplace.call(typedArrayVectorTemplate, /Int32Array/g, 'Uint32Array') + ' return vector;')();
var Float64Vector = new Function(originalStringReplace.call(typedArrayVectorTemplate, /Int32Array/g, 'Float64Array') + ' return vector;')();
Int32Vector.prototype.asGetProperty = function (namespaces, name, flags) {
  if (typeof name === 'number') {
    return this.asGetNumericProperty(name);
  }
  return asGetProperty.call(this, namespaces, name, flags);
};
Int32Vector.prototype.asSetProperty = function (namespaces, name, flags, value) {
  if (typeof name === 'number') {
    this.asSetNumericProperty(name, value);
    return;
  }
  return asSetProperty.call(this, namespaces, name, flags, value);
};
Uint32Vector.prototype.asGetProperty = function (namespaces, name, flags) {
  if (typeof name === 'number') {
    return this.asGetNumericProperty(name);
  }
  return asGetProperty.call(this, namespaces, name, flags);
};
Uint32Vector.prototype.asSetProperty = function (namespaces, name, flags, value) {
  if (typeof name === 'number') {
    this.asSetNumericProperty(name, value);
    return;
  }
  return asSetProperty.call(this, namespaces, name, flags, value);
};
Float64Vector.prototype.asGetProperty = function (namespaces, name, flags) {
  if (typeof name === 'number') {
    return this.asGetNumericProperty(name);
  }
  return asGetProperty.call(this, namespaces, name, flags);
};
Float64Vector.prototype.asSetProperty = function (namespaces, name, flags, value) {
  if (typeof name === 'number') {
    this.asSetNumericProperty(name, value);
    return;
  }
  return asSetProperty.call(this, namespaces, name, flags, value);
};
var GenericVector = function () {
    function vector(length, fixed, type) {
      length = length | 0;
      this._fixed = !(!fixed);
      this._buffer = new Array(length);
      this._type = type;
      this._defaultValue = type ? type.defaultValue : null;
      this._fill(0, length, this._defaultValue);
    }
    vector.applyType = function applyType(type) {
      function parameterizedVector(length, fixed) {
        vector.call(this, length, fixed, type);
      }
      parameterizedVector.prototype = Object.create(vector.prototype);
      parameterizedVector.callable = vector.callable;
      return parameterizedVector;
    };
    vector.callable = function (object) {
      if (object instanceof vector) {
        return object;
      }
      var length = object.asGetProperty(undefined, 'length');
      if (length !== undefined) {
        var v = new vector(length, false);
        for (var i = 0; i < length; i++) {
          v.asSetNumericProperty(i, object.asGetPublicProperty(i));
        }
        return v;
      }
      unexpected();
    };
    vector.prototype._fill = function (index, length, value) {
      for (var i = 0; i < length; i++) {
        this._buffer[index + i] = value;
      }
    };
    vector.prototype.toString = function () {
      var str = '';
      for (var i = 0; i < this._buffer.length; i++) {
        str += this._buffer[i];
        if (i < this._buffer.length - 1) {
          str += ',';
        }
      }
      return str;
    };
    vector.prototype.every = function (callback, thisObject) {
      for (var i = 0; i < this._buffer.length; i++) {
        if (!callback.call(thisObject, this.asGetNumericProperty(i), i, this)) {
          return false;
        }
      }
      return true;
    };
    vector.prototype.filter = function (callback, thisObject) {
      var v = new vector();
      for (var i = 0; i < this._buffer.length; i++) {
        if (callback.call(thisObject, this.asGetNumericProperty(i), i, this)) {
          v.push(this.asGetNumericProperty(i));
        }
      }
      return v;
    };
    vector.prototype.some = function (callback, thisObject) {
      if (arguments.length !== 2) {
        throwError('ArgumentError', Errors.WrongArgumentCountError);
      } else if (!isFunction(callback)) {
        throwError('ArgumentError', Errors.CheckTypeFailedError);
      }
      for (var i = 0; i < this._buffer.length; i++) {
        if (callback.call(thisObject, this.asGetNumericProperty(i), i, this)) {
          return true;
        }
      }
      return false;
    };
    vector.prototype.forEach = function (callback, thisObject) {
      if (!isFunction(callback)) {
        throwError('ArgumentError', Errors.CheckTypeFailedError);
      }
      for (var i = 0; i < this._buffer.length; i++) {
        callback.call(thisObject, this.asGetNumericProperty(i), i, this);
      }
    };
    vector.prototype.map = function (callback, thisObject) {
      if (!isFunction(callback)) {
        throwError('ArgumentError', Errors.CheckTypeFailedError);
      }
      var v = new vector();
      for (var i = 0; i < this._buffer.length; i++) {
        v.push(callback.call(thisObject, this.asGetNumericProperty(i), i, this));
      }
      return v;
    };
    vector.prototype.push = function () {
      this._checkFixed();
      for (var i = 0; i < arguments.length; i++) {
        this._buffer.push(this._coerce(arguments[i]));
      }
    };
    vector.prototype.pop = function () {
      this._checkFixed();
      if (this._buffer.length === 0) {
        return undefined;
      }
      return this._buffer.pop();
    };
    vector.prototype.reverse = function () {
      this._buffer.reverse();
    };
    vector.CASEINSENSITIVE = 1;
    vector.DESCENDING = 2;
    vector.UNIQUESORT = 4;
    vector.RETURNINDEXEDARRAY = 8;
    vector.NUMERIC = 16;
    function defaultCompareFunction(a, b) {
      return String(a).localeCompare(String(b));
    }
    function compare(a, b, options, compareFunction) {
      assertNotImplemented(!(options & CASEINSENSITIVE), 'CASEINSENSITIVE');
      assertNotImplemented(!(options & UNIQUESORT), 'UNIQUESORT');
      assertNotImplemented(!(options & RETURNINDEXEDARRAY), 'RETURNINDEXEDARRAY');
      var result = 0;
      if (!compareFunction) {
        compareFunction = defaultCompareFunction;
      }
      if (options & NUMERIC) {
        a = toNumber(a);
        b = toNumber(b);
        result = a < b ? -1 : a > b ? 1 : 0;
      } else {
        result = compareFunction(a, b);
      }
      if (options & DESCENDING) {
        result *= -1;
      }
      return result;
    }
    vector.prototype.sort = function (comparator) {
      return this._buffer.sort(comparator);
    };
    vector.prototype.asGetNumericProperty = function (i) {
      checkArguments && asCheckVectorGetNumericProperty(i, this._buffer.length);
      return this._buffer[i];
    };
    vector.prototype._coerce = function (v) {
      if (this._type) {
        return this._type.coerce(v);
      } else if (v === undefined) {
        return null;
      }
      return v;
    };
    vector.prototype.asSetNumericProperty = function (i, v) {
      checkArguments && asCheckVectorSetNumericProperty(i, this._buffer.length, this._fixed);
      this._buffer[i] = this._coerce(v);
    };
    vector.prototype.shift = function () {
      this._checkFixed();
      if (this._buffer.length === 0) {
        return undefined;
      }
      return this._buffer.shift();
    };
    vector.prototype._checkFixed = function () {
      if (this._fixed) {
        throwError('RangeError', Errors.VectorFixedError);
      }
    };
    vector.prototype.unshift = function () {
      if (!arguments.length) {
        return;
      }
      this._checkFixed();
      var items = [];
      for (var i = 0; i < arguments.length; i++) {
        items.push(this._coerce(arguments[i]));
      }
      this._buffer.unshift.apply(this._buffer, items);
    };
    Object.defineProperty(vector.prototype, 'length', {
      get: function () {
        return this._buffer.length;
      },
      set: function (length) {
        length = length >>> 0;
        if (length > this._buffer.length) {
          for (var i = this._buffer.length; i < length; i++) {
            this._buffer[i] = this._defaultValue;
          }
        } else {
          this._buffer.length = length;
        }
        true;
      }
    });
    vector.prototype._spliceHelper = function (index, insertCount, deleteCount, args, offset) {
      insertCount = clamp(insertCount, 0, args.length - offset);
      deleteCount = clamp(deleteCount, 0, this._buffer.length - index);
      var items = [];
      for (var i = 0; i < insertCount; i++) {
        items.push(this._coerce(args.asGetNumericProperty(offset + i)));
      }
      this._buffer.splice.apply(this._buffer, [
        index,
        deleteCount
      ].concat(items));
    };
    vector.prototype.asGetEnumerableKeys = function () {
      if (vector.prototype === this) {
        return Object.prototype.asGetEnumerableKeys.call(this);
      }
      var keys = [];
      for (var i = 0; i < this._buffer.length; i++) {
        keys.push(i);
      }
      return keys;
    };
    vector.prototype.asHasProperty = function (namespaces, name, flags) {
      if (vector.prototype === this || !isNumeric(name)) {
        return Object.prototype.asHasProperty.call(this, namespaces, name, flags);
      }
      var index = toNumber(name);
      return index >= 0 && index < this._buffer.length;
    };
    return vector;
  }();
GenericVector.prototype.asGetProperty = function (namespaces, name, flags) {
  if (typeof name === 'number') {
    return this.asGetNumericProperty(name);
  }
  return asGetProperty.call(this, namespaces, name, flags);
};
GenericVector.prototype.asSetProperty = function (namespaces, name, flags, value) {
  if (typeof name === 'number') {
    this.asSetNumericProperty(name, value);
    return;
  }
  return asSetProperty.call(this, namespaces, name, flags, value);
};
function arraySort(o, args) {
  if (args.length === 0) {
    return o.sort();
  }
  var compareFunction, options = 0;
  if (args[0] instanceof Function) {
    compareFunction = args[0];
  } else if (isNumber(args[0])) {
    options = args[0];
  }
  if (isNumber(args[1])) {
    options = args[1];
  }
  o.sort(function (a, b) {
    return asCompare(a, b, options, compareFunction);
  });
  return o;
}
function ArrayClass(domain, scope, instanceConstructor, baseClass) {
  var c = new Class('Array', Array, ApplicationDomain.passthroughCallable(Array));
  c.extendBuiltin(baseClass);
  var CACHE_NUMERIC_COMPARATORS = true;
  var numericComparatorCache = createEmptyObject();
  c.native = {
    static: {
      _pop: function _pop(o) {
        return o.pop();
      },
      _reverse: function _reverse(o) {
        return o.reverse();
      },
      _concat: function _concat(o, args) {
        return o.concat.apply(o, args);
      },
      _shift: function _shift(o) {
        return o.shift();
      },
      _slice: function _slice(o, A, B) {
        return o.slice(A, B);
      },
      _unshift: function _unshift(o, args) {
        return o.unshift.apply(o, args);
      },
      _splice: function _splice(o, args) {
        return o.splice.apply(o, args);
      },
      _sort: function _sort(o, args) {
        if (args.length === 0) {
          return o.sort();
        }
        var compareFunction, options = 0;
        if (args[0] instanceof Function) {
          compareFunction = args[0];
        } else if (isNumber(args[0])) {
          options = args[0];
        }
        if (isNumber(args[1])) {
          options = args[1];
        }
        o.sort(function (a, b) {
          return asCompare(a, b, options, compareFunction);
        });
        return o;
      },
      _sortOn: function _sortOn(o, names, options) {
        if (isString(names)) {
          names = [
            names
          ];
        }
        if (isNumber(options)) {
          options = [
            options
          ];
        }
        for (var i = names.length - 1; i >= 0; i--) {
          var key = Multiname.getPublicQualifiedName(names[i]);
          if (CACHE_NUMERIC_COMPARATORS && options[i] & SORT_NUMERIC) {
            var str = 'var x = toNumber(a.' + key + '), y = toNumber(b.' + key + ');';
            if (options[i] & SORT_DESCENDING) {
              str += 'return x < y ? 1 : (x > y ? -1 : 0);';
            } else {
              str += 'return x < y ? -1 : (x > y ? 1 : 0);';
            }
            var numericComparator = numericComparatorCache[str];
            if (!numericComparator) {
              numericComparator = numericComparatorCache[str] = new Function('a', 'b', str);
            }
            o.sort(numericComparator);
          } else {
            o.sort(function (a, b) {
              return asCompare(a[key], b[key], options[i] | 0);
            });
          }
        }
        return o;
      },
      _indexOf: function _indexOf(o, searchElement, fromIndex) {
        return o.indexOf(searchElement, fromIndex);
      },
      _lastIndexOf: function _lastIndexOf(o, searchElement, fromIndex) {
        return o.lastIndexOf(searchElement, fromIndex);
      },
      _every: function _every(o, callback, thisObject) {
        for (var i = 0; i < o.length; i++) {
          if (callback.call(thisObject, o[i], i, o) !== true) {
            return false;
          }
        }
        return false;
      },
      _filter: function _filter(o, callback, thisObject) {
        var result = [];
        for (var i = 0; i < o.length; i++) {
          if (callback.call(thisObject, o[i], i, o) === true) {
            result.push(o[i]);
          }
        }
        return result;
      },
      _forEach: function _forEach(o, callback, thisObject) {
        return o.forEach(callback, thisObject);
      },
      _map: function _map(o, callback, thisObject) {
        return o.map(callback, thisObject);
      },
      _some: function _some(o, callback, thisObject) {
        return o.some(callback, thisObject);
      }
    },
    instance: {
      pop: Array.prototype.pop,
      push: Array.prototype.push,
      unshift: Array.prototype.unshift,
      length: {
        get: function length() {
          return this.length;
        },
        set: function length(newLength) {
          this.length = newLength;
        }
      }
    }
  };
  c.coerce = function (value) {
    return value;
  };
  c.isInstanceOf = function (value) {
    return true;
  };
  return c;
}
var XMLClass, XMLListClass, QNameClass, ASXML, XML, ASXMLList, XMLList;
var isXMLType, isXMLName, XMLParser;
(function () {
  function XMLEncoder(ancestorNamespaces, indentLevel, prettyPrinting) {
    function visit(node, encode) {
      if (node.isXML) {
        switch (node.kind) {
        case 'element':
          return encode.element(node);
        case 'attribute':
          return encode.attribute(node);
        case 'text':
          return encode.text(node);
        case 'cdata':
          return encode.cdata(node);
        case 'comment':
          return encode.comment(node);
        case 'processing-instruction':
          return encode.pi(node);
        }
      } else if (node.isXMLList) {
        return encode.list(node);
      } else {
        throw 'Not implemented';
      }
    }
    function encode(node, encoder) {
      return visit(node, {
        element: function (n) {
          var s, a;
          var ns = n.name.mn.namespaces[0];
          var prefix = ns.prefix ? ns.prefix + ':' : '';
          s = '<' + prefix + n.name.localName;
          var namespaceDeclarations = [];
          if (ns.prefix || ns.uri) {
            namespaceDeclarations.push(ns);
          }
          if (prefix) {
            namespaceDeclarations[ns.prefix] = true;
          }
          var t = n;
          while (t) {
            for (var i = 0; i < t.inScopeNamespaces.length; i++) {
              ns = t.inScopeNamespaces[i];
              if (!namespaceDeclarations[ns.prefix]) {
                namespaceDeclarations.push(ns);
                namespaceDeclarations[ns.prefix] = true;
              }
            }
            t = t.parent;
          }
          for (var i = 0; i < namespaceDeclarations.length; i++) {
            a = namespaceDeclarations[i];
            if (a.prefix) {
              s += ' xmlns:' + a.prefix + '="' + a.uri + '"';
            } else {
              s += ' xmlns="' + a.uri + '"';
            }
          }
          for (var i = 0; i < n.attributes.length; i++) {
            a = n.attributes[i];
            var ns = n.name.uri;
            var prefix = n.prefix ? ns.prefix + ':' : '';
            var name = prefix + a.name.localName;
            s += ' ' + name + '="' + a.value + '"';
          }
          if (n.children.length) {
            s += '>';
            for (var i = 0; i < n.children.length; i++) {
              s += visit(n.children[i], this);
            }
            s += '</' + prefix + n.name.mn.name + '>';
          } else {
            s += '/>';
          }
          return s;
        },
        text: function (text) {
          return escapeAttributeValue(text.value);
        },
        attribute: function (n) {
          return escapeAttributeValue(n.value);
        },
        cdata: function (n) {
        },
        comment: function (n) {
        },
        pi: function (n) {
        },
        doctype: function (n) {
        },
        list: function (n) {
          var s = '';
          for (var i = 0; i < n.children.length; i++) {
            if (i > 0) {
              s += '\n';
            }
            s += toXMLString(n.children[i], []);
          }
          return s;
        }
      });
    }
    this.encode = encode;
  }
  function escapeAttributeValue(v) {
    return v.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;');
  }
  XMLParser = function XMLParser() {
    function parseXml(s, sink) {
      var i = 0, scopes = [
          {
            space: 'default',
            xmlns: '',
            namespaces: {
              'xmlns': 'http://www.w3.org/2000/xmlns/',
              'xml': 'http://www.w3.org/XML/1998/namespace'
            }
          }
        ];
      function trim(s) {
        return s.replace(/^\s+/, '').replace(/\s+$/, '');
      }
      function resolveEntities(s) {
        return s.replace(/&([^;]+);/g, function (all, entity) {
          if (entity.substring(0, 2) === '#x') {
            return String.fromCharCode(parseInt(entity.substring(2), 16));
          } else if (entity.substring(0, 1) === '#') {
            return String.fromCharCode(parseInt(entity.substring(1), 10));
          }
          switch (entity) {
          case 'lt':
            return '<';
          case 'gt':
            return '>';
          case 'amp':
            return '&';
          }
          throw 'Unknown entity: ' + entity;
        });
      }
      function isWhitespacePreserved() {
        for (var j = scopes.length - 1; j >= 0; --j) {
          if (scopes[j].space === 'preserve') {
            return true;
          }
        }
        return false;
      }
      function lookupDefaultNs() {
        for (var j = scopes.length - 1; j >= 0; --j) {
          if (scopes[j].hasOwnProperty('xmlns')) {
            return scopes[j].xmlns;
          }
        }
      }
      function lookupNs(prefix) {
        for (var j = scopes.length - 1; j >= 0; --j) {
          if (scopes[j].namespaces.hasOwnProperty(prefix)) {
            return scopes[j].namespaces[prefix];
          }
        }
        throw 'Unknown namespace: ' + prefix;
      }
      function getName(name, resolveDefaultNs) {
        var j = name.indexOf(':');
        if (j >= 0) {
          var namespace = lookupNs(name.substring(0, j));
          var prefix = name.substring(0, j);
          var localName = name.substring(j + 1);
          return {
            name: namespace + '::' + localName,
            localName: localName,
            prefix: prefix,
            namespace: namespace
          };
        } else if (resolveDefaultNs) {
          return {
            name: name,
            localName: name,
            prefix: '',
            namespace: lookupDefaultNs()
          };
        } else {
          return {
            name: name,
            localName: name,
            prefix: '',
            namespace: ''
          };
        }
      }
      var whitespaceMap = {
          '10': true,
          '13': true,
          '9': true,
          '32': true
        };
      function isWhitespace(s, index) {
        return s.charCodeAt(index) in whitespaceMap;
      }
      function parseContent(s, start) {
        var pos = start, name, attributes = [];
        function skipWs() {
          while (pos < s.length && isWhitespace(s, pos)) {
            ++pos;
          }
        }
        while (pos < s.length && !isWhitespace(s, pos) && s.charAt(pos) !== '>' && s.charAt(pos) !== '/') {
          ++pos;
        }
        name = s.substring(start, pos);
        skipWs();
        while (pos < s.length && s.charAt(pos) !== '>' && s.charAt(pos) !== '/' && s.charAt(pos) !== '?') {
          skipWs();
          var attrName = '', attrValue = '';
          while (pos < s.length && !isWhitespace(s, pos) && s.charAt(pos) !== '=') {
            attrName += s.charAt(pos);
            ++pos;
          }
          skipWs();
          if (s.charAt(pos) !== '=')
            throw '\'=\' expected';
          ++pos;
          skipWs();
          var attrEndChar = s.charAt(pos);
          if (attrEndChar !== '"' && attrEndChar !== '\'')
            throw 'Quote expected';
          var attrEndIndex = s.indexOf(attrEndChar, ++pos);
          if (attrEndIndex < 0)
            throw new 'Unexpected EOF[6]'();
          attrValue = s.substring(pos, attrEndIndex);
          attributes.push({
            name: attrName,
            value: resolveEntities(attrValue)
          });
          pos = attrEndIndex + 1;
          skipWs();
        }
        return {
          name: name,
          attributes: attributes,
          parsed: pos - start
        };
      }
      while (i < s.length) {
        var ch = s.charAt(i);
        var j = i;
        if (ch === '<') {
          ++j;
          var ch2 = s.charAt(j), q, name;
          switch (ch2) {
          case '/':
            ++j;
            q = s.indexOf('>', j);
            if (q < 0) {
              throw 'Unexpected EOF[1]';
            }
            name = getName(s.substring(j, q), true);
            sink.endElement(name);
            scopes.pop();
            j = q + 1;
            break;
          case '?':
            ++j;
            var content = parseContent(s, j);
            if (s.substring(j + content.parsed, j + content.parsed + 2) != '?>') {
              throw 'Unexpected EOF[2]';
            }
            sink.pi(content.name, content.attributes);
            j += content.parsed + 2;
            break;
          case '!':
            if (s.substring(j + 1, j + 3) === '--') {
              q = s.indexOf('-->', j + 3);
              if (q < 0) {
                throw 'Unexpected EOF[3]';
              }
              sink.comment(s.substring(j + 3, q));
              j = q + 3;
            } else if (s.substring(j + 1, j + 8) === '[CDATA[') {
              q = s.indexOf(']]>', j + 8);
              if (q < 0) {
                throw 'Unexpected EOF[4]';
              }
              sink.cdata(s.substring(j + 8, q));
              j = q + 3;
            } else if (s.substring(j + 1, j + 8) === 'DOCTYPE') {
              var q2 = s.indexOf('[', j + 8), complexDoctype = false;
              q = s.indexOf('>', j + 8);
              if (q < 0) {
                throw 'Unexpected EOF[5]';
              }
              if (q2 > 0 && q > q2) {
                q = s.indexOf(']>', j + 8);
                if (q < 0) {
                  throw 'Unexpected EOF[7]';
                }
                complexDoctype = true;
              }
              var doctypeContent = s.substring(j + 8, q + (complexDoctype ? 1 : 0));
              sink.doctype(doctypeContent);
              j = q + (complexDoctype ? 2 : 1);
            } else {
              throw 'Unknown !tag';
            }
            break;
          default:
            var content = parseContent(s, j);
            var isClosed = false;
            if (s.substring(j + content.parsed, j + content.parsed + 2) === '/>') {
              isClosed = true;
            } else if (s.substring(j + content.parsed, j + content.parsed + 1) !== '>') {
              throw 'Unexpected EOF[2]';
            }
            var scope = {
                namespaces: []
              };
            var contentAttributes = content.attributes;
            for (q = 0; q < contentAttributes.length; ++q) {
              var attribute = contentAttributes[q];
              var attributeName = attribute.name;
              if (attributeName.substring(0, 6) === 'xmlns:') {
                var prefix = attributeName.substring(6);
                var uri = attribute.value;
                scope.namespaces[prefix] = trim(uri);
                scope.namespaces.push({
                  uri: uri,
                  prefix: prefix
                });
                delete contentAttributes[q];
              } else if (attributeName === 'xmlns') {
                var uri = attribute.value;
                scope.namespaces['xmlns'] = trim(uri);
                scope.namespaces.push({
                  uri: uri,
                  prefix: ''
                });
                delete contentAttributes[q];
              } else if (attributeName.substring(0, 4) === 'xml:') {
                scope[attributeName.substring(4)] = trim(attribute.value);
              } else if (attributeName.substring(0, 3) === 'xml') {
                throw 'Invalid xml attribute';
              } else {
              }
            }
            scopes.push(scope);
            var attributes = [];
            for (q = 0; q < contentAttributes.length; ++q) {
              attribute = contentAttributes[q];
              if (attribute) {
                attributes.push({
                  name: getName(attribute.name, false),
                  value: attribute.value
                });
              }
            }
            sink.beginElement(getName(content.name, true), attributes, scope, isClosed);
            j += content.parsed + (isClosed ? 2 : 1);
            if (isClosed)
              scopes.pop();
            break;
          }
        } else {
          do {
            if (++j >= s.length)
              break;
          } while (s.charAt(j) !== '<');
          var text = s.substring(i, j);
          var isWs = text.replace(/^\s+/, '').length === 0;
          if (!isWs || isWhitespacePreserved()) {
            sink.text(resolveEntities(text), isWs);
          }
        }
        i = j;
      }
    }
    this.parseFromString = function (s, mimeType) {
      var currentElement = new XML('element', '', '', '');
      var elementsStack = [];
      parseXml(s, {
        beginElement: function (name, attrs, scope, isEmpty) {
          var parent = currentElement;
          elementsStack.push(parent);
          currentElement = createNode('element', name.namespace, name.localName, name.prefix);
          for (var i = 0; i < attrs.length; ++i) {
            var rawAttr = attrs[i];
            var attr = createNode('attribute', rawAttr.name.namespace, rawAttr.name.localName, rawAttr.name.prefix);
            attr.value = rawAttr.value;
            currentElement.attributes.push(attr);
          }
          var namespaces = scope.namespaces;
          for (var i = 0; i < namespaces.length; ++i) {
            var rawNs = namespaces[i];
            var ns = ASNamespace.createNamespace(rawNs.uri, rawNs.prefix);
            currentElement.inScopeNamespaces.push(ns);
          }
          parent.insert(parent.length(), currentElement);
          if (isEmpty) {
            currentElement = elementsStack.pop();
          }
        },
        endElement: function (name) {
          currentElement = elementsStack.pop();
        },
        text: function (text, isWhitespace) {
          var node = createNode('text', '', '');
          node.value = text;
          currentElement.insert(currentElement.length(), node);
        },
        cdata: function (text) {
          var node = createNode('text', '', '');
          node.value = text;
          currentElement.insert(currentElement.length(), node);
        },
        comment: function (text) {
        },
        pi: function (name, attrs) {
        },
        doctype: function (text) {
        }
      });
      return currentElement;
    };
    function createNode(kind, uri, name, prefix) {
      return new XML(kind, uri, name, prefix);
    }
  };
  var xmlParser = new XMLParser();
  isXMLType = function isXMLType(val) {
    return val.isXML || val.isXMLList;
  };
  function toString(node) {
    if (typeof node === 'object' && node !== null) {
      switch (node.kind) {
      case 'text':
      case 'attribute':
        return node.value;
      default:
        if (node.hasSimpleContent()) {
          var str = '';
          node.children.forEach(function (v, i) {
            str += toString(v);
          });
          return str;
        }
        return toXMLString(node);
      }
    } else {
      return String(node);
    }
  }
  function toXMLString(node, ancestorNamespaces, indentLevel) {
    return new XMLEncoder(ancestorNamespaces, indentLevel, true).encode(node);
  }
  function toXML(v) {
    if (v === null) {
      throw new TypeError(formatErrorMessage(Errors.ConvertNullToObjectError));
    } else if (v === undefined) {
      throw new TypeError(formatErrorMessage(Errors.ConvertUndefinedToObjectError));
    } else if (v.isXML) {
      return v;
    } else if (v.isXMLList) {
      if (v.length() === 1) {
        return v.children[0];
      }
      throw new TypeError(formatErrorMessage(Errors.XMLMarkupMustBeWellFormed));
    } else {
      var x = xmlParser.parseFromString(String(v));
      if (x.length() === 0) {
        var x = new XML('text');
        return x;
      } else if (x.length() === 1) {
        x.children[0].parent = null;
        return x.children[0];
      }
      throw 'SyntaxError in ToXML';
    }
  }
  var defaultNamespace = '';
  function toXMLList(value) {
    if (value === null) {
      throw new TypeError(formatErrorMessage(Errors.ConvertNullToObjectError));
    } else if (value === undefined) {
      throw new TypeError(formatErrorMessage(Errors.ConvertUndefinedToObjectError));
    } else if (value instanceof XML) {
      var xl = new XMLList(value.parent, value.name);
      xl.append(value);
      return xl;
    } else if (value instanceof XMLList) {
      return value;
    } else {
      var s = '<parent xmlns=\'' + defaultNamespace + '\'>' + String(value) + '</parent>';
      var x = new ASXML(s);
      var xl = new XMLList();
      for (var i = 0; i < x.length(); i++) {
        var v = x.children[i];
        v.parent = null;
        xl.append(v);
      }
      return xl;
    }
  }
  function toAttributeName(v) {
    if (v === undefined || v === null || typeof v === 'boolean' || typeof v === 'number') {
      throw 'TypeError: invalid operand to ToAttributeName()';
    } else if (isXMLType(v)) {
      v = toString(v);
    } else if (v instanceof Object && v !== null) {
      if (v instanceof QName) {
        return new QName(v.uri, v.localName, true);
      }
      v = toString(v);
    }
    if (typeof v === 'string') {
      var ns = new ASNamespace();
      var qn = new QName(ns, v, true);
    } else {
    }
    return qn;
  }
  function toXMLName(mn) {
    return new QName(mn);
  }
  function getDefaultNamespace(scope) {
    while (scope) {
      var obj = scope.object;
      if (obj.defaultNamepsace !== undefined) {
        return obj.defaultNamespace;
      }
      scope = scope.parent;
    }
    var ns = ASNamespace.createNamespace('', '');
    return ns;
  }
  isXMLName = function isXMLName(v) {
    try {
      var qn = new QName(v);
    } catch (e) {
      return false;
    }
    return true;
  };
  function asGetProperty(namespaces, name, flags, isMethod) {
    var mn = isNumeric(name) ? toNumber(name) : name instanceof QName ? name.mn : new Multiname(namespaces ? namespaces : [
        ASNamespace.PUBLIC
      ], name, flags);
    return this.getProperty(mn, isMethod);
  }
  function asSetProperty(namespaces, name, flags, value) {
    var mn = isNumeric(name) ? toNumber(name) : name instanceof QName ? name.mn : new Multiname(namespaces ? namespaces : [
        ASNamespace.PUBLIC
      ], name, flags);
    this.setProperty(mn, value);
  }
  function asHasProperty(namespaces, name, flags) {
    var mn = isNumeric(name) ? toNumber(name) : name instanceof QName ? name.mn : new Multiname(namespaces ? namespaces : [
        ASNamespace.PUBLIC
      ], name, flags);
    return this.hasProperty(mn);
  }
  function asCallProperty(namespaces, name, flags, isLex, args) {
    var receiver = isLex ? null : this;
    var property = this.asGetProperty(namespaces, name, flags, true);
    if (!property) {
      return this.toString().asCallProperty(namespaces ? namespaces : [
        ASNamespace.PUBLIC
      ], name, flags, isLex, args);
    }
    return property.apply(receiver, args);
  }
  var ATTR_NAME = 1;
  var ELEM_NAME = 2;
  var ANY_NAME = 4;
  var ANY_NAMESPACE = 8;
  function nameKind(mn) {
    var flags = 0;
    if (mn.isAttribute()) {
      flags |= ATTR_NAME;
    } else {
      flags |= ELEM_NAME;
    }
    if (mn.isAnyName()) {
      flags |= ANY_NAME;
    }
    if (mn.isAnyNamespace()) {
      flags |= ANY_NAMESPACE;
    }
    return flags;
  }
  XMLClass = function XMLClass(runtime, scope, instanceConstructor, baseClass) {
    var FLAG_IGNORE_COMMENTS = 1;
    var FLAG_IGNORE_PROCESSING_INSTRUCTIONS = 2;
    var FLAG_IGNORE_WHITESPACE = 4;
    var FLAG_PRETTY_PRINTING = 8;
    ASXML = function (value) {
      if (!(this instanceof ASXML)) {
        if (value instanceof ASXML) {
          return value;
        }
        return new ASXML(value);
      }
      if (value === null || value === undefined) {
        value = '';
      }
      var x = toXML(value);
      if (isXMLType(value)) {
        x = x.deepCopy();
      }
      return x;
    };
    XML = function (kind, uri, name, prefix) {
      if (kind === undefined) {
        kind = 'text';
      }
      if (uri === undefined) {
        uri = '';
      }
      if (name === undefined) {
        name = '';
      }
      this.init(kind, uri, name, prefix);
    };
    var c = new Class('XML', ASXML, ApplicationDomain.passthroughCallable(ASXML));
    c.flags = FLAG_IGNORE_COMMENTS | FLAG_IGNORE_PROCESSING_INSTRUCTIONS | FLAG_IGNORE_WHITESPACE | FLAG_PRETTY_PRINTING;
    c.prettyIndent = 2;
    c.extend(baseClass);
    var Xp = XML.prototype = ASXML.prototype;
    Xp.init = function init(kind, uri, name, prefix) {
      this.name = new QName(new Multiname([
        new ASNamespace(prefix, uri)
      ], name));
      this.kind = kind;
      this.parent = null;
      this.inScopeNamespaces = [];
      switch (kind) {
      case 'element':
        this.attributes = [];
        this.children = [];
        break;
      case 'attribute':
      case 'text':
        this.value = '';
        break;
      default:
        break;
      }
      return this;
    };
    Xp.length = function () {
      if (!this.children) {
        return 0;
      }
      return this.children.length;
    };
    Xp.canHandleProperties = true;
    Xp.deepCopy = function () {
      return new ASXML(toXMLString(this));
    };
    Xp.resolveValue = function resolveValue() {
      return this;
    };
    Xp.hasSimpleContent = function hasSimpleContent() {
      if (this.kind === 'comment' || this.kind === 'processing-instruction') {
        return false;
      }
      var result = true;
      if (this.children) {
        this.children.forEach(function (v) {
          if (v.kind === 'element') {
            result = false;
          }
        });
      }
      return result;
    };
    Xp.asGetEnumerableKeys = function asGetEnumerableKeys() {
      if (Xp === this) {
        return Object.prototype.asGetEnumerableKeys.call(this);
      }
      var keys = [];
      this.children.forEach(function (v, i) {
        keys.push(v.name);
      });
      return keys;
    };
    function setAttribute(node, name, value) {
      if (node.nodeType === Node.DOCUMENT_NODE) {
        node.childNodes[0].setAttribute(name, value);
      } else if (node.nodeType === Node.ELEMENT_NODE) {
        node.setAttribute(name, value);
      } else {
        throw 'error or unhandled case in setAttribute';
      }
    }
    Xp.setProperty = function (p, v) {
      var x, i, c, n;
      x = this;
      if (p === p >>> 0) {
        throw 'TypeError in XML.prototype.setProperty(): invalid property name ' + p;
      }
      if (x.kind === 'text' || x.kind === 'comment' || x.kind === 'processing-instruction' || x.kind === 'attribute') {
        return;
      }
      if (!v || !v.isXML && !v.isXMLList || v.kind === 'text' || v.kind === 'attribute') {
        c = toString(v);
      } else {
        c = v.deepCopy();
      }
      n = toXMLName(p);
      if (n.isAttr) {
        if (!this.attributes) {
          return;
        }
        this.attributes.forEach(function (v, i, o) {
          if (v.name === n.localName) {
            delete o[i];
          }
        });
        var a = new XML('attribute', n.uri, n.localName);
        a.value = v;
        a.parent = this;
        this.attributes.push(a);
        return;
      }
      var isValidName = isXMLName(n);
      if (!isValidName && n.localName !== '*') {
        return;
      }
      var i = undefined;
      var primitiveAssign = !isXMLType(c) && n.localName !== '*';
      for (var k = x.length() - 1; k >= 0; k--) {
        if ((n.isAny || x.children[k].kind === 'element' && x.children[k].name.localName === n.localName) && (n.uri === null || x.children[k].kind === 'element' && x.children[k].name.uri === n.uri)) {
          if (i !== undefined) {
            x.deleteByIndex(String(i));
          }
          i = k;
        }
      }
      if (i === undefined) {
        i = x.length();
        if (primitiveAssign) {
          if (n.uri === null) {
            var name = new QName(getDefaultNamespace(scope), n);
          } else {
            var name = new QName(n);
          }
          var y = new XML('element', name.uri, name.localName, name.prefix);
          y.parent = x;
          var ns = name.getNamespace();
          x.replace(String(i), y);
          y.addInScopeNamespace(ns);
        }
      }
      if (primitiveAssign) {
        x.children[i].children = [];
        var s = toString(c);
        if (s !== '') {
          x.children[i].replace('0', s);
        }
      } else {
        x.replace(String(i), c);
      }
      return;
    };
    Xp.asGetProperty = asGetProperty;
    Xp.asGetResolvedStringProperty = asGetResolvedStringPropertyFallback;
    Xp.asSetProperty = asSetProperty;
    Xp.asHasProperty = asHasProperty;
    Xp.asCallProperty = asCallProperty;
    Xp.getProperty = function (mn, isMethod) {
      if (isMethod) {
        var resolved = Multiname.isQName(mn) ? mn : this.resolveMultinameProperty(mn.namespaces, mn.name, mn.flags);
        return this[Multiname.getQualifiedName(resolved)];
      }
      if (!Multiname.isQName(mn) && isNumeric(mn)) {
        if (Number(0) === 0) {
          return this;
        }
        return null;
      }
      var x = this;
      var name = toXMLName(mn);
      var xl = new XMLList(x, name);
      var flags = nameKind(name.mn);
      var anyName = flags & ANY_NAME;
      var anyNamespace = flags & ANY_NAMESPACE;
      if (flags & ATTR_NAME) {
        if (x.attributes) {
          x.attributes.forEach(function (v, i) {
            if ((anyName || v.name.localName === name.localName) && (anyNamespace || v.name.uri === name.uri)) {
              xl.append(v);
            }
          });
        }
      } else {
        x.children.forEach(function (v, i) {
          if ((anyName || v.kind === 'element' && v.name.localName === name.localName) && (anyNamespace || v.kind === 'element' && v.name.uri === name.uri)) {
            xl.append(v);
          }
        });
      }
      return xl;
    };
    Xp.hasProperty = function (mn, isMethod) {
      if (isMethod) {
        var resolved = Multiname.isQName(mn) ? mn : this.resolveMultinameProperty(mn.namespaces, mn.name, mn.flags);
        return !(!this[Multiname.getQualifiedName(resolved)]);
      }
      if (!Multiname.isQName(mn) && isNumeric(mn)) {
        if (Number(0) === 0) {
          return true;
        }
        return false;
      }
      var name = toXMLName(mn);
      var flags = nameKind(name.mn);
      var anyName = flags & ANY_NAME;
      var anyNamespace = flags & ANY_NAMESPACE;
      if (flags & ATTR_NAME) {
        return this.attributes.some(function (v, i) {
          if ((anyName || v.name.localName === name.localName) && (anyNamespace || v.name.uri === name.uri)) {
            return true;
          }
        });
        if (x.attributes) {
          x.attributes.forEach(function (v, i) {
            if ((anyName || v.name.localName === name.localName) && (anyNamespace || v.name.uri === name.uri)) {
              xl.append(v);
            }
          });
        }
      } else {
        if (this.children.some(function (v, i) {
            if ((anyName || v.kind === 'element' && v.name.localName === name.localName) && (anyNamespace || v.kind === 'element' && v.name.uri === name.uri)) {
              return true;
            }
          })) {
          return true;
        }
        var resolved = Multiname.isQName(mn) ? mn : this.resolveMultinameProperty(mn.namespaces, mn.name, mn.flags);
        return !(!this[Multiname.getQualifiedName(resolved)]);
      }
    };
    Xp.delete = function (key, isMethod) {
      notImplemented('XML.[[Delete]]');
    };
    Xp.deleteByIndex = function (p) {
      var x = this;
      var i = p >>> 0;
      if (String(i) !== String(p)) {
        throw 'TypeError in XML.prototype.deleteByIndex(): invalid index ' + p;
      }
      if (p < x.length()) {
        if (x.children[p]) {
          x.children[p].parent = null;
          delete x.children[p];
          for (q = i + 1; q < x.length(); q++) {
            x.children[q - 1] = x.children[q];
          }
          x.children.length = x.children.length - 1;
        }
      }
    };
    Xp.isXML = true;
    Xp.insert = function insert(p, v) {
      var x, s, i, n;
      x = this;
      if (x.kind === 'text' || x.kind === 'comment' || x.kind === 'processing-instruction' || x.kind === 'attribute') {
        return;
      }
      i = p >>> 0;
      if (String(p) !== String(i)) {
        throw 'TypeError in XML.prototype.insert(): invalid property name ' + p;
      }
      if (x.kind === 'element') {
        var a = x;
        while (a) {
          if (a === v) {
            throw 'Error in XML.prototype.insert()';
          }
          a = a.parent;
        }
      }
      if (x.isXMLList) {
        n = x.length();
        if (n === 0) {
          return;
        }
      } else {
        n = 1;
      }
      for (var j = x.length() - 1; j >= i; j--) {
        x[j + n] = x[j];
      }
      if (x.isXMLList) {
        n = v.length();
        for (var j = 0; j < n; j++) {
          v.children[j].parent = x;
          x[i + j] = v[j];
        }
      } else {
        v.parent = x;
        x.children[i] = v;
      }
    };
    Xp.replace = function (p, v) {
      var x, s;
      x = this;
      if (x.kind === 'text' || x.kind === 'comment' || x.kind === 'processing-instruction' || x.kind === 'attribute') {
        return;
      }
      var i = p >>> 0;
      if (String(p) !== String(i)) {
        throw 'TypeError in XML.prototype.replace(): invalid name ' + p;
      }
      if (i >= x.length()) {
        p = String(x.length());
      }
      if (v.kind === 'element') {
        var a = x;
        while (a) {
          if (a === v) {
            throw 'Error in XML.prototype.replace()';
          }
          a = a.parent;
        }
      }
      if (v.kind === 'element' || v.kind === 'text' || v.kind === 'comment' || v.kind === 'processing-instruction') {
        v.parent = x;
        if (x[p]) {
          x.children[p].parent = null;
        }
        x.children[p] = v;
      } else if (x.isXMLList) {
        x.deleteByIndex(p);
        x.insert(p, v);
      } else {
        s = toString(v);
        t = new XML();
        t.parent = x;
        t.value = s;
        if (x[p]) {
          x.children[p].parent = null;
        }
        x.children[p] = t;
      }
    };
    Xp.addInScopeNamespace = function (ns) {
      var x, s;
      x = this;
      if (x.kind === 'text' || x.kind === 'comment' || x.kind === 'processing-instruction' || x.kind === 'attribute') {
        return;
      }
      if (ns.prefix !== undefined) {
        if (ns.prefix === '' && x.name.uri === '') {
          return;
        }
        var match = null;
        x.inScopeNamespaces.forEach(function (v, i) {
          if (v.prefix === ns.prefix) {
            match = v;
          }
        });
        if (match !== null && match.uri !== ns.uri) {
          x.inScopeNamespaces.forEach(function (v, i) {
            if (v.prefix === match.prefix) {
              x.inScopeNamespaces[i] = ns;
            }
          });
        }
        if (x.name.prefix === ns.prefix) {
          x.name.prefix = undefined;
        }
        x.attributes.forEach(function (v, i) {
          if (v.name.prefix === ns.name.prefix) {
            v.name.prefix = undefined;
          }
        });
      }
    };
    Xp.descendants = function (name) {
      name = toXMLName(name);
      var x = this;
      var xl = new XMLList();
      if (x.kind !== 'element') {
        return xl;
      }
      if (name.isAttr) {
        this.attributes.forEach(function (v, i) {
          if (name.isAny || name.localName === v.name.localName) {
            xl.append(v);
          }
        });
      } else {
        this.children.forEach(function (v, i) {
          if (name.isAny || name.localName === v.name.localName) {
            xl.append(v);
          }
        });
      }
      this.children.forEach(function (v, i) {
        xl.append(v.descendants(name));
      });
      return xl;
    };
    Xp.comments = function () {
      var x = this;
      var xl = new XMLList(x, null);
      x.children.forEach(function (v, i) {
        if (v.kind === 'comment') {
          xl.append(v);
        }
      });
      return xl;
    };
    Xp.text = function () {
      var x = this;
      var xl = new XMLList(x, null);
      x.children.forEach(function (v, i) {
        if (v.kind === 'text') {
          xl.append(v);
        }
      });
      return xl;
    };
    c.native = {
      static: {
        ignoreComments: {
          get: function ignoreComments() {
            return getBitFlags(c.flags, FLAG_IGNORE_COMMENTS);
          },
          set: function ignoreComments(newIgnore) {
            c.flags = setBitFlags(c.flags, FLAG_IGNORE_COMMENTS, newIgnore);
          }
        },
        ignoreProcessingInstructions: {
          get: function ignoreProcessingInstructions() {
            return getBitFlags(c.flags, FLAG_IGNORE_PROCESSING_INSTRUCTIONS);
          },
          set: function ignoreProcessingInstructions(newIgnore) {
            c.flags = setBitFlags(c.flags, FLAG_IGNORE_PROCESSING_INSTRUCTIONS, newIgnore);
          }
        },
        ignoreWhitespace: {
          get: function ignoreWhitespace() {
            return getBitFlags(c.flags, FLAG_IGNORE_WHITESPACE);
          },
          set: function ignoreWhitespace(newIgnore) {
            c.flags = setBitFlags(c.flags, FLAG_IGNORE_WHITESPACE, newIgnore);
          }
        },
        prettyPrinting: {
          get: function prettyPrinting() {
            return getBitFlags(c.flags, FLAG_PRETTY_PRINTING);
          },
          set: function prettyPrinting(newPretty) {
            c.flags = setBitFlags(c.flags, FLAG_PRETTY_PRINTING, newPretty);
          }
        },
        prettyIndent: {
          get: function prettyIndent() {
            return c.prettyIndent;
          },
          set: function prettyIndent(newIndent) {
            c.prettyIndent = newIndent;
          }
        }
      },
      instance: {
        toString: function () {
          return toString(this);
        },
        hasOwnProperty: function hasOwnProperty(P) {
          somewhatImplemented('XML.hasOwnProperty');
          return this.hasProperty(P);
        },
        propertyIsEnumerable: function propertyIsEnumerable(P) {
          notImplemented('XML.propertyIsEnumerable');
        },
        addNamespace: function addNamespace(ns) {
          notImplemented('XML.addNamespace');
        },
        appendChild: function appendChild(child) {
          var children = this.getProperty('*');
          children.setProperty(children.length(), child);
          return this;
        },
        attribute: function attribute(name) {
          return this.getProperty(toAttributeName(name));
        },
        attributes: function attributes() {
          return this.getProperty(toAttributeName('*'));
        },
        child: function child(name) {
          return this.getProperty(name);
        },
        childIndex: function childIndex() {
          notImplemented('XML.childIndex');
        },
        children: function children() {
          var list = new XMLList();
          Array.prototype.push.apply(list.children, this.children);
          return list;
        },
        comments: function comments() {
          return this.comments();
        },
        contains: function contains(value) {
          notImplemented('XML.contains');
        },
        copy: function copy() {
          return this.deepCopy();
        },
        descendants: function descendants(name) {
          if (name === undefined) {
            name = '*';
          }
          return this.descendants(name);
        },
        elements: function elements(name) {
          var x = this;
          var any = false;
          if (name === undefined) {
            name = '*';
            any = true;
          }
          var name = toXMLName(name);
          var xl = new XMLList(this.parent, name);
          x.children.forEach(function (v, i) {
            if (v.kind === 'element' && (any || v.name.localName === name.localName) && (name.uri === null || v.kind === 'element' && v.name.uri === name.uri)) {
              xl.append(v);
            }
          });
          return xl;
        },
        hasComplexContent: function hasComplexContent() {
          notImplemented('XML.hasComplexContent');
        },
        hasSimpleContent: function hasSimpleContent() {
          return this.hasSimpleContent();
        },
        inScopeNamespaces: function inScopeNamespaces() {
          notImplemented('XML.inScopeNamespaces');
        },
        insertChildAfter: function insertChildAfter(child1, child2) {
          notImplemented('XML.insertChildAfter');
        },
        insertChildBefore: function insertChildBefore(child1, child2) {
          notImplemented('XML.insertChildBefore');
        },
        localName: function localName() {
          return this.name.localName;
        },
        name: function name() {
          return this.name;
        },
        _namespace: function _namespace(prefix, argc) {
          somewhatImplemented('XML._namespace()');
          return this.name.uri;
        },
        namespaceDeclarations: function namespaceDeclarations() {
          return new XMLList();
        },
        nodeKind: function nodeKind() {
          return this.kind;
        },
        normalize: function normalize() {
          notImplemented('XML.normalize');
        },
        parent: function parent() {
          notImplemented('XML.parent');
        },
        processingInstructions: function processingInstructions(name) {
          notImplemented('XML.processingInstructions');
        },
        prependChild: function prependChild(value) {
          notImplemented('XML.prependChild');
        },
        removeNamespace: function removeNamespace(ns) {
          notImplemented('XML.removeNamespace');
        },
        replace: function replace(propertyName, value) {
          var c, x, s, i;
          x = this;
          if (x.kind === 'text' || x.kind === 'comment' || x.kind === 'processing-instruction' || x.kind === 'attribute') {
            return x;
          }
          if (!isXMLType(value)) {
            c = value.toString();
          } else {
            c = value.deepCopy();
          }
          var i = propertyName >>> 0;
          if (String(propertyName) === String(i)) {
            x.replace(propertyName, c);
            return x;
          }
          n = new QName(propertyName);
          i = undefined;
          for (k = x.length() - 1; k >= 0; k--) {
            var v = x.children[k];
            if (n.isAny || v.kind === 'element' && v.name.localName === n.localName && (n.uri === null || v.kind === 'element' && v.name.uri === n.uri)) {
              if (i !== undefined) {
                x.deleteByIndex(String(i));
              }
              i = k;
            }
          }
          if (i !== undefined) {
            x.replace(i.toString(), c);
          }
          return x;
        },
        setChildren: function setChildren(value) {
          notImplemented('XML.setChildren');
        },
        setLocalName: function setLocalName(name) {
          notImplemented('XML.setLocalName');
        },
        setName: function setName(name) {
          notImplemented('XML.setName');
        },
        setNamespace: function setNamespace(ns) {
          notImplemented('XML.setNamespace');
        },
        text: function text() {
          return this.text();
        },
        toXMLString: function () {
          return toXMLString(this);
        },
        notification: function notification() {
          notImplemented('XML.notification');
        },
        setNotification: function setNotification(f) {
          notImplemented('XML.setNotification');
        }
      }
    };
    return c;
  };
  XMLListClass = function XMLListClass(runtime, scope, instanceConstructor, baseClass) {
    ASXMLList = function (value) {
      if (!(this instanceof ASXMLList)) {
        return callXMLList(value);
      }
      return constructXMLList(value);
    };
    function callXMLList(v) {
      if (v === null || v === undefined) {
        v = '';
      }
      return toXMLList(v);
    }
    function constructXMLList(val) {
      if (val === null || val === undefined) {
        val = '';
      }
      if (val.isXMLList) {
        var xl = new XMLList();
        xl.append(val);
        return xl;
      }
      return toXMLList(val);
    }
    XMLList = function (targetObject, targetProperty) {
      this.targetObject = targetObject ? targetObject : null;
      this.targetProperty = targetProperty ? targetProperty : null;
      this.children = [];
    };
    var c = new Class('XMLList', ASXMLList, ApplicationDomain.passthroughCallable(ASXMLList));
    c.extend(baseClass);
    var XLp = XMLList.prototype = ASXMLList.prototype;
    XLp.canHandleProperties = true;
    XLp.hasSimpleContent = function hasSimpleContent() {
      if (this.length() === 0) {
        return true;
      } else if (this.length() === 1) {
        return toXML(this).hasSimpleContent();
      }
      var result = true;
      this.children.forEach(function (v) {
        if (v.kind === 'element') {
          result = false;
        }
      });
      return result;
    };
    XLp.asGetProperty = asGetProperty;
    XLp.asGetResolvedStringProperty = asGetResolvedStringPropertyFallback;
    XLp.asSetProperty = asSetProperty;
    XLp.asHasProperty = asHasProperty;
    XLp.asCallProperty = asCallProperty;
    XLp.setProperty = function (mn, v, isMethod) {
      var x, i, r;
      x = this;
      i = mn >>> 0;
      if (String(mn) === String(i)) {
        var targetObject = this.targetObject;
        var targetProperty = this.targetProperty;
        if (targetObject !== null) {
          r = targetObject.resolveValue();
          if (r === null) {
            return;
          }
        } else {
          r = null;
        }
        if (i >= x.length()) {
          if (r && r.isXMLList) {
            if (r.length !== 1) {
              return;
            } else {
              r = r.children[0];
            }
          }
          if (r && r.kind !== 'element') {
            return;
          }
          var y = new XML();
          y.parent = r;
          y.name = x.targetProperty;
          if (targetProperty === null || targetProperty.localName === '*') {
            y.name = null;
            y.kind = 'text';
          } else if (targetProperty.isAttr) {
            var attributeExists = r.getProperty(y.name);
            if (attributeExists.length() > 0) {
              return;
            }
            r.kind = 'attribute';
          } else {
            y.kind = 'element';
          }
          i = x.length();
          if (y.kind !== 'attribute') {
            if (r !== null) {
              if (i > 0) {
                var j = 0;
                while (j < r.length() - 1 && r.children[j] !== x.children[i - 1]) {
                  j++;
                }
              } else {
                var j = r.length() - 1;
              }
              r.insert(String(j + 1), y);
            }
            if (v.isXML) {
              y.name = v.name;
            } else if (v.isXMLList) {
              y.name = v.targetProperty;
            }
          }
          x.append(y);
        }
        if (!v.isXML && !v.isXMLList || v.kind === 'text' || v.kind === 'attribute') {
          v = toString(v);
        }
        if (x.children[i].kind === 'attribute') {
          var z = toAttributeName(x.children[i].name);
          x.children[i].parent.setProperty(z, v);
          var attr = x.children[i].parent.getProperty(z);
          x.children[i] = attr.children[0];
        } else if (v.isXMLList) {
          var c = v.deepCopy();
          var parent = x.children[i].parent;
          if (parent !== null) {
            var q;
            parent.children.some(function (v, p) {
              if (v == x.children[i]) {
                q = p;
                return true;
              }
            });
            parent.replace(q, c);
            c.children.forEach(function (v, j) {
              c.children[j] = parent.children[q >>> 0 + j];
            });
          }
          if (c.length() === 0) {
            for (var j = x + 1; j < x.length() - 1; j++) {
              x.children[String(j - 1)] = x.children[j];
            }
          } else {
            for (var j = x.length() - 1; j >= i + 1; j--) {
              x.children[String(j + c.length() - 1)] = x.children[j];
            }
          }
          for (var j = 0; j < c.length(); j++) {
            x.children[i + j] = c.children[j];
          }
        } else if (v.isXML || (k = x.children[i].kind) === 'text' || k === 'comment' || k === 'processing-instruction') {
          var parent = x.children[i].parent;
          if (parent !== null) {
            var q;
            parent.children.some(function (v, p) {
              if (v == x.children[i]) {
                q = p;
                return true;
              }
            });
            parent.replace(q, v);
            var v = parent.children[q];
          }
          if (typeof v === 'string') {
            var t = new XML('text');
            t.parent = x;
            t.value = v;
            x.children[i] = t;
          } else {
            x.children[i] = v;
          }
        } else {
          x.children[i].setProperty('*', v);
        }
      } else if (x.length() <= 1) {
        if (x.length() === 0) {
          r = x.resolveValue();
          if (r === null || r.length() !== 1) {
            return;
          }
          x.append(r);
        }
        x.children[0].setProperty(mn, v);
      }
    };
    XLp.getProperty = function (mn, isMethod) {
      if (isMethod) {
        var resolved = Multiname.isQName(mn) ? mn : this.resolveMultinameProperty(mn.namespaces, mn.name, mn.flags);
        return this[Multiname.getQualifiedName(resolved)];
      }
      var x = this;
      var i = mn >>> 0;
      if (String(mn) === String(i)) {
        return x.children[mn];
      }
      var name = toXMLName(mn);
      var xl = new XMLList(this, name);
      x.children.forEach(function (v, i) {
        var xl2;
        if (v.kind === 'element') {
          xl2 = v.getProperty(mn);
          if (xl2.length() > 0) {
            xl.append(xl2);
          }
        }
      });
      return xl;
    };
    XLp.hasProperty = function (mn, isMethod) {
      if (isMethod) {
        var resolved = Multiname.isQName(mn) ? mn : this.resolveMultinameProperty(mn.namespaces, mn.name, mn.flags);
        return !(!this[Multiname.getQualifiedName(resolved)]);
      }
      var x = this;
      var i = mn >>> 0;
      if (String(mn) === String(i)) {
        return !(!x.children[mn]);
      }
      var name = toXMLName(mn);
      return this.children.some(function (v, i) {
        var xl2 = v.getProperty(mn);
        if (xl2.length() > 0) {
          return true;
        }
      });
    };
    XLp.delete = function (key, isMethod) {
    };
    XLp.append = function (val) {
      if (val.isXMLList) {
        this.targetObject = val.targetObject;
        this.targetProperty = val.targetProperty;
        if (val.length() === 0) {
          return;
        }
        for (var i = 0; i < val.length(); i++) {
          this.children.push(val.children[i]);
        }
      } else if (val.isXML) {
        this.children.push(val);
      }
    };
    XLp.length = function () {
      return this.children.length;
    };
    XLp.resolve = function () {
      var base = this.targetObject.resolveValue();
      if (base === null) {
        return null;
      }
      var target = this.targetObject.getProperty(this.targetProperty);
      if (base.length === 0) {
        notImplemented('XMLList.resolve');
        base.setProperty(this.targetProperty, '');
        target = base.getProperty(this.targetProperty);
        return target;
      }
    };
    XLp.deepCopy = function () {
      var xl = new XMLList();
      this.children.forEach(function (v, i) {
        xl.children[i] = v.deepCopy();
      });
      return xl;
    };
    XLp.descendants = function (name) {
      var xl = new XMLList(null);
      this.children.forEach(function (v, i) {
        if (v.kind === 'element') {
          xl.append(v.descendants(name));
        }
      });
      return xl;
    };
    XLp.resolveValue = function resolveValue() {
      if (this.length() > 0) {
        return this;
      }
      var x = this;
      var name = x.name;
      var targetObject = x.targetObject;
      var targetProperty = x.targetProperty;
      if (targetObject === null || targetProperty === null || name.isAttr || name.isAny) {
        return null;
      }
      var base = targetObject.resolveValue();
      if (base === null) {
        return null;
      }
      var target = base.getProperty(targetProperty);
      if (target.length() === 0) {
        if (base.isXMLList && base.length() > 1) {
          return null;
        }
        base.setProperty(targetProperty, '');
        target = base.getProperty(targetProperty);
      }
      return target;
    };
    XLp.asGetEnumerableKeys = function asGetEnumerableKeys() {
      if (XLp === this) {
        return Object.prototype.asGetEnumerableKeys.call(this);
      }
      var keys = [];
      this.children.forEach(function (v, i) {
        keys.push(i);
      });
      return keys;
    };
    c.native = {
      instance: {
        init: function () {
        }
      }
    };
    XLp.isXMLList = true;
    c.native = {
      static: {},
      instance: {
        toString: function () {
          return toString(this);
        },
        hasOwnProperty: function hasOwnProperty(P) {
          somewhatImplemented('XMLList.hasOwnProperty');
          return this.hasProperty(P);
        },
        propertyIsEnumerable: function propertyIsEnumerable(P) {
          notImplemented('XMLList.propertyIsEnumerable');
        },
        attribute: function attribute(name) {
          return this.getProperty(toAttributeName(name));
        },
        attributes: function attributes() {
          return this.getProperty(toAttributeName('*'));
        },
        child: function child(propertyName) {
          notImplemented('XMLList.child');
        },
        children: function children() {
          var list = new XMLList();
          for (var i = 0; i < this.children.length; i++) {
            var child = this.children[i];
            Array.prototype.push.apply(list.children, child.children);
          }
          return list;
        },
        comments: function comments() {
          var x = this;
          var xl = new XMLList(x, null);
          x.children.forEach(function (v, i) {
            if (v.kind === 'element') {
              xl.append(v.comments());
            }
          });
          return xl;
        },
        contains: function contains(value) {
          for (var i = 0; i < this.children.length; i++) {
            if (this.children[i] === value) {
              return true;
            }
          }
          return false;
        },
        copy: function copy() {
          return this.deepCopy();
        },
        descendants: function descendants(name) {
          return this.descendants(name === undefined ? '*' : name);
        },
        elements: function elements(name) {
          var x = this;
          var any = false;
          if (name === undefined) {
            name = '*';
            any = true;
          }
          var name = toXMLName(name);
          var xl = new XMLList(x, name);
          x.children.forEach(function (v, i) {
            if (v.kind === 'element') {
              xl.append(v.comments());
            }
          });
          return xl;
        },
        hasComplexContent: function hasComplexContent() {
          notImplemented('XMLList.hasComplexContent');
        },
        hasSimpleContent: function hasSimpleContent() {
          return this.hasSimpleContent();
        },
        length: function length() {
          return this.children.length;
        },
        name: function name() {
          return toXML(this).name;
        },
        normalize: function normalize() {
          notImplemented('XMLList.normalize');
        },
        parent: function parent() {
          notImplemented('XMLList.parent');
        },
        processingInstructions: function processingInstructions(name) {
          notImplemented('XMLList.processingInstructions');
        },
        text: function text() {
          var x = this;
          var xl = new XMLList(x, null);
          x.children.forEach(function (v, i) {
            if (v.kind === 'text' || v.kind === 'element') {
              xl.append(v.text());
            }
          });
          return xl;
        },
        toXMLString: function () {
          return toXMLString(this);
        },
        addNamespace: function addNamespace(ns) {
          notImplemented('XMLList.addNamespace');
        },
        appendChild: function appendChild(child) {
          toXML(this).appendChild(child);
          return this;
        },
        childIndex: function childIndex() {
          notImplemented('XMLList.childIndex');
        },
        inScopeNamespaces: function inScopeNamespaces() {
          notImplemented('XMLList.inScopeNamespaces');
        },
        insertChildAfter: function insertChildAfter(child1, child2) {
          notImplemented('XMLList.insertChildAfter');
        },
        insertChildBefore: function insertChildBefore(child1, child2) {
          notImplemented('XMLList.insertChildBefore');
        },
        nodeKind: function nodeKind() {
          return toXML(this).kind;
        },
        _namespace: function _namespace(prefix, argc) {
          notImplemented('XMLList._namespace');
        },
        localName: function localName() {
          notImplemented('XMLList.localName');
        },
        namespaceDeclarations: function namespaceDeclarations() {
          somewhatImplemented('XMLList.prototype.namespaceDeclarations()');
          return new XMLList();
        },
        prependChild: function prependChild(value) {
          notImplemented('XMLList.prependChild');
        },
        removeNamespace: function removeNamespace(ns) {
          notImplemented('XMLList.removeNamespace');
        },
        replace: function replace(propertyName, value) {
          toXML(this).replace(propertyName, value);
          return this;
        },
        setChildren: function setChildren(value) {
          notImplemented('XMLList.setChildren');
        },
        setLocalName: function setLocalName(name) {
          notImplemented('XMLList.setLocalName');
        },
        setName: function setName(name) {
          notImplemented('XMLList.setName');
        },
        setNamespace: function setNamespace(ns) {
          notImplemented('XMLList.setNamespace');
        }
      }
    };
    return c;
  };
  QNameClass = function QNameClass(runtime, scope, instanceConstructor, baseClass) {
    QName = function QName(ns, name, isAttr) {
      if (!(this instanceof QName)) {
        if (name === undefined && ns instanceof QName) {
          return ns;
        } else {
          return new QName(ns, name);
        }
      }
      if (name === undefined) {
        name = ns;
        ns = undefined;
      }
      if (typeof ns === 'string' || ns instanceof QName) {
        ns = new ASNamespace(ns);
      }
      var mn;
      if (name instanceof QName) {
        if (ns === undefined) {
          mn = name.mn;
        } else {
          mn = new Multiname([
            ns
          ], name.mn.getName());
        }
      } else if (name instanceof Multiname) {
        if (ns === undefined) {
          if (name.isQName() || name.isAnyName() || name.isAnyNamespace()) {
            mn = name;
          } else {
            mn = new Multiname([
              getDefaultNamespace(scope)
            ], name.getName(), name.flags);
          }
        } else {
          mn = new Multiname([
            ns
          ], name.getName(), name.flags);
        }
      } else if (name === '*') {
        mn = new Multiname([], null, isAttr ? Multiname.ATTRIBUTE : 0);
      } else if (name === '@*') {
        mn = new Multiname([], null, Multiname.ATTRIBUTE);
      } else {
        ns = ns === undefined ? getDefaultNamespace(scope) : ns;
        if (name === undefined) {
          mn = new Multiname([
            ns
          ], '');
        } else {
          mn = new Multiname([
            ns
          ], toString(name), isAttr ? Multiname.ATTRIBUTE : 0);
        }
      }
      this.mn = mn;
      this.isAny = mn.isAnyName();
      this.isAnyNamespace = mn.isAnyNamespace();
      this.isAttr = mn.isAttribute();
    };
    var c = new Class('QName', QName, ApplicationDomain.passthroughCallable(QName));
    c.extend(baseClass);
    QNp = QName.prototype;
    defineNonEnumerableGetter(QNp, 'localName', function () {
      if (!this._localName) {
        this._localName = this.isAny ? '*' : this.mn.getName();
      }
      return this._localName;
    });
    defineNonEnumerableGetter(QNp, 'uri', function () {
      if (!this._uri) {
        var ns = this.mn.namespaces[0];
        this._uri = ns && ns.uri ? ns.uri : this.isAny || this.isAnyNamespace ? null : '';
      }
      return this._uri;
    });
    defineNonEnumerableGetter(QNp, 'prefix', function () {
      return this.mn.namespaces[0].prefix;
    });
    defineNonEnumerableSetter(QNp, 'prefix', function (prefix) {
      this.mn.namespaces[0].prefix = prefix;
    });
    QNp.getNamespace = function (isns) {
      if (this.uri === null) {
        throw 'TypeError in QName.prototype.getNamespace()';
      }
      if (!isns) {
        isns = [];
      }
      var ns;
      for (var i = 0; i < isns.length; i++) {
        if (this.uri === isns[i].uri) {
          ns = isns[i];
        }
      }
      if (!ns) {
        ns = ASNamespace.createNamespace(this.uri);
      }
      return ns;
    };
    c.native = {
      static: {},
      instance: {
        localName: {
          get: function localName() {
            return this.localName;
          }
        },
        uri: {
          get: function uri() {
            return this.uri;
          }
        }
      }
    };
    return c;
  };
}());
var AMFUtils = function AMFUtilsClosure() {
    var AMF0_NUMBER_MARKER = 0;
    var AMF0_BOOLEAN_MARKER = 1;
    var AMF0_STRING_MARKER = 2;
    var AMF0_OBJECT_MARKER = 3;
    var AMF0_NULL_MARKER = 5;
    var AMF0_UNDEFINED_MARKER = 6;
    var AMF0_REFERENCE_MARKER = 7;
    var AMF0_ECMA_ARRAY_MARKER = 8;
    var AMF0_OBJECT_END_MARKER = 9;
    var AMF0_STRICT_ARRAY_MARKER = 10;
    var AMF0_DATE_MARKER = 11;
    var AMF0_LONG_STRING_MARKER = 12;
    var AMF0_XML_MARKER = 15;
    var AMF0_TYPED_OBJECT_MARKER = 16;
    var AMF0_AVMPLUS_MARKER = 17;
    function writeString(ba, s) {
      if (s.length > 65535) {
        throw 'AMF short string exceeded';
      }
      if (!s.length) {
        ba.writeByte(0);
        ba.writeByte(0);
        return;
      }
      var bytes = utf8decode(s);
      ba.writeByte(bytes.length >> 8 & 255);
      ba.writeByte(bytes.length & 255);
      for (var i = 0; i < bytes.length; i++) {
        ba.writeByte(bytes[i]);
      }
    }
    function readString(ba) {
      var byteLength = ba.readByte() << 8 | ba.readByte();
      if (!byteLength) {
        return '';
      }
      var buffer = new Uint8Array(byteLength);
      for (var i = 0; i < byteLength; i++) {
        buffer[i] = ba.readByte();
      }
      return utf8encode(buffer);
    }
    function writeDouble(ba, value) {
      var buffer = new ArrayBuffer(8);
      var view = new DataView(buffer);
      view.setFloat64(0, value, false);
      for (var i = 0; i < buffer.byteLength; i++) {
        ba.writeByte(view.getUint8(i));
      }
    }
    function readDouble(ba) {
      var buffer = new ArrayBuffer(8);
      var view = new DataView(buffer);
      for (var i = 0; i < buffer.byteLength; i++) {
        view.setUint8(i, ba.readByte());
      }
      return view.getFloat64(0, false);
    }
    function setAvmProperty(obj, propertyName, value) {
      obj.asSetPublicProperty(propertyName, value);
    }
    var amf0 = {
        write: function (ba, obj) {
          switch (typeof obj) {
          case 'boolean':
            ba.writeByte(AMF0_BOOLEAN_MARKER);
            ba.writeByte(obj ? 1 : 0);
            break;
          case 'number':
            ba.writeByte(AMF0_NUMBER_MARKER);
            writeDouble(ba, obj);
            break;
          case 'undefined':
            ba.writeByte(AMF0_UNDEFINED_MARKER);
            break;
          case 'string':
            ba.writeByte(AMF0_STRING_MARKER);
            writeString(ba, obj);
            break;
          case 'object':
            if (obj === null) {
              ba.writeByte(AMF0_NULL_MARKER);
            } else if (Array.isArray(obj)) {
              ba.writeByte(AMF0_ECMA_ARRAY_MARKER);
              ba.writeByte(obj.length >>> 24 & 255);
              ba.writeByte(obj.length >> 16 & 255);
              ba.writeByte(obj.length >> 8 & 255);
              ba.writeByte(obj.length & 255);
              forEachPublicProperty(obj, function (key, value) {
                writeString(ba, key);
                this.write(ba, value);
              }, this);
              ba.writeByte(0);
              ba.writeByte(0);
              ba.writeByte(AMF0_OBJECT_END_MARKER);
            } else {
              ba.writeByte(AMF0_OBJECT_MARKER);
              forEachPublicProperty(obj, function (key, value) {
                writeString(ba, key);
                this.write(ba, value);
              }, this);
              ba.writeByte(0);
              ba.writeByte(0);
              ba.writeByte(AMF0_OBJECT_END_MARKER);
            }
            return;
          }
        },
        read: function (ba) {
          var marker = ba.readByte();
          switch (marker) {
          case AMF0_NUMBER_MARKER:
            return readDouble(ba);
          case AMF0_BOOLEAN_MARKER:
            return !(!ba.readByte());
          case AMF0_STRING_MARKER:
            return readString(ba);
          case AMF0_OBJECT_MARKER:
            var obj = {};
            while (true) {
              var key = readString(ba);
              if (!key.length)
                break;
              setAvmProperty(obj, key, this.read(ba));
            }
            if (ba.readByte() !== AMF0_OBJECT_END_MARKER) {
              throw 'AMF0 End marker is not found';
            }
            return obj;
          case AMF0_NULL_MARKER:
            return null;
          case AMF0_UNDEFINED_MARKER:
            return undefined;
          case AMF0_ECMA_ARRAY_MARKER:
            var obj = [];
            obj.length = ba.readByte() << 24 | ba.readByte() << 16 | ba.readByte() << 8 | ba.readByte();
            while (true) {
              var key = readString(ba);
              if (!key.length)
                break;
              setAvmProperty(obj, key, this.read(ba));
            }
            if (ba.readByte() !== AMF0_OBJECT_END_MARKER) {
              throw 'AMF0 End marker is not found';
            }
            return obj;
          case AMF0_STRICT_ARRAY_MARKER:
            var obj = [];
            obj.length = ba.readByte() << 24 | ba.readByte() << 16 | ba.readByte() << 8 | ba.readByte();
            for (var i = 0; i < obj.length; i++) {
              obj[i] = this.read(ba);
            }
            return obj;
          case AMF0_AVMPLUS_MARKER:
            return readAmf3Data(ba, {});
          default:
            throw 'AMF0 Unknown marker ' + marker;
          }
        }
      };
    var AMF3_UNDEFINED_MARKER = 0;
    var AMF3_NULL_MARKER = 1;
    var AMF3_FALSE_MARKER = 2;
    var AMF3_TRUE_MARKER = 3;
    var AMF3_INTEGER_MARKER = 4;
    var AMF3_DOUBLE_MARKER = 5;
    var AMF3_STRING_MARKER = 6;
    var AMF3_XML_DOC_MARKER = 7;
    var AMF3_DATE_MARKER = 8;
    var AMF3_ARRAY_MARKER = 9;
    var AMF3_OBJECT_MARKER = 10;
    var AMF3_XML_MARKER = 11;
    var AMF3_BYTEARRAY_MARKER = 12;
    var AMF3_VECTOR_INT_MARKER = 13;
    var AMF3_VECTOR_UINT_MARKER = 14;
    var AMF3_VECTOR_DOUBLE_MARKER = 15;
    var AMF3_VECTOR_OBJECT_MARKER = 16;
    var AMF3_DICTIONARY_MARKER = 17;
    function readU29(ba) {
      var b1 = ba.readByte();
      if ((b1 & 128) === 0) {
        return b1;
      }
      var b2 = ba.readByte();
      if ((b2 & 128) === 0) {
        return (b1 & 127) << 7 | b2;
      }
      var b3 = ba.readByte();
      if ((b3 & 128) === 0) {
        return (b1 & 127) << 14 | (b2 & 127) << 7 | b3;
      }
      var b4 = ba.readByte();
      return (b1 & 127) << 22 | (b2 & 127) << 15 | (b3 & 127) << 8 | b4;
    }
    function writeU29(ba, value) {
      if ((value & 4294967168) === 0) {
        ba.writeByte(value & 127);
      } else if ((value & 4294950912) === 0) {
        ba.writeByte(128 | value >> 7 & 127);
        ba.writeByte(value & 127);
      } else if ((value & 4292870144) === 0) {
        ba.writeByte(128 | value >> 14 & 127);
        ba.writeByte(128 | value >> 7 & 127);
        ba.writeByte(value & 127);
      } else if ((value & 3221225472) === 0) {
        ba.writeByte(128 | value >> 22 & 127);
        ba.writeByte(128 | value >> 15 & 127);
        ba.writeByte(128 | value >> 8 & 127);
        ba.writeByte(value & 255);
      } else {
        throw 'AMF3 U29 range';
      }
    }
    function readUTF8vr(ba, caches) {
      var u29s = readU29(ba);
      if (u29s === 1) {
        return '';
      }
      var stringsCache = caches.stringsCache || (caches.stringsCache = []);
      if ((u29s & 1) === 0) {
        return stringsCache[u29s >> 1];
      }
      var byteLength = u29s >> 1;
      var buffer = new Uint8Array(byteLength);
      for (var i = 0; i < byteLength; i++) {
        buffer[i] = ba.readByte();
      }
      var value = utf8encode(buffer);
      stringsCache.push(value);
      return value;
    }
    function writeUTF8vr(ba, value, caches) {
      if (value === '') {
        ba.writeByte(1);
        return;
      }
      var stringsCache = caches.stringsCache || (caches.stringsCache = []);
      var index = stringsCache.indexOf(value);
      if (index >= 0) {
        writeU29(ba, index << 1);
        return;
      }
      stringsCache.push(value);
      var bytes = utf8decode(value);
      writeU29(ba, 1 | bytes.length << 1);
      for (var i = 0; i < bytes.length; i++) {
        ba.writeByte(bytes[i]);
      }
    }
    function readAmf3Data(ba, caches) {
      var marker = ba.readByte();
      switch (marker) {
      case AMF3_NULL_MARKER:
        return null;
      case AMF3_UNDEFINED_MARKER:
        return undefined;
      case AMF3_FALSE_MARKER:
        return false;
      case AMF3_TRUE_MARKER:
        return true;
      case AMF3_INTEGER_MARKER:
        return readU29(ba);
      case AMF3_DOUBLE_MARKER:
        return readDouble(ba);
      case AMF3_STRING_MARKER:
        return readUTF8vr(ba, caches);
      case AMF3_DATE_MARKER:
        return new Date(readDouble(ba));
      case AMF3_OBJECT_MARKER:
        var u29o = readU29(ba);
        if ((u29o & 1) === 0) {
          return caches.objectsCache[u29o >> 1];
        }
        if ((u29o & 4) !== 0) {
          throw 'AMF3 Traits-Ext is not supported';
        }
        var traits, objectClass;
        if ((u29o & 2) === 0) {
          traits = caches.traitsCache[u29o >> 2];
          objectClass = traits.class;
        } else {
          traits = {};
          var aliasName = readUTF8vr(ba, caches);
          traits.className = aliasName;
          objectClass = aliasName && aliasesCache.names[aliasName];
          traits.class = objectClass;
          traits.isDynamic = (u29o & 8) !== 0;
          traits.members = [];
          var slots = objectClass && objectClass.instanceBindings.slots;
          for (var i = 0, j = u29o >> 4; i < j; i++) {
            var traitName = readUTF8vr(ba, caches);
            var slot = null;
            for (var j = 1; slots && j < slots.length; j++) {
              if (slots[j].name.name === traitName) {
                slot = slots[j];
                break;
              }
            }
            traits.members.push(slot ? Multiname.getQualifiedName(slot.name) : Multiname.getPublicQualifiedName(traitName));
          }
          (caches.traitsCache || (caches.traitsCache = [])).push(traits);
        }
        var obj = objectClass ? objectClass.createInstance() : {};
        (caches.objectsCache || (caches.objectsCache = [])).push(obj);
        for (var i = 0; i < traits.members.length; i++) {
          var value = readAmf3Data(ba, caches);
          obj[traits.members[i]] = value;
        }
        if (traits.isDynamic) {
          while (true) {
            var key = readUTF8vr(ba, caches);
            if (!key.length)
              break;
            var value = readAmf3Data(ba, caches);
            setAvmProperty(obj, key, value);
          }
        }
        return obj;
      case AMF3_ARRAY_MARKER:
        var u29o = readU29(ba);
        if ((u29o & 1) === 0) {
          return caches.objectsCache[u29o >> 1];
        }
        var obj = [];
        (caches.objectsCache || (caches.objectsCache = [])).push(obj);
        var densePortionLength = u29o >> 1;
        while (true) {
          var key = readUTF8vr(ba, caches);
          if (!key.length)
            break;
          var value = readAmf3Data(ba, caches);
          setAvmProperty(obj, key, value);
        }
        for (var i = 0; i < densePortionLength; i++) {
          var value = readAmf3Data(ba, caches);
          setAvmProperty(obj, i, value);
        }
        return obj;
      default:
        throw 'AMF3 Unknown marker ' + marker;
      }
    }
    function writeCachedReference(ba, obj, caches) {
      var objectsCache = caches.objectsCache || (caches.objectsCache = []);
      var index = objectsCache.indexOf(obj);
      if (index < 0) {
        objectsCache.push(obj);
        return false;
      }
      writeU29(ba, index << 1);
      return true;
    }
    function writeAmf3Data(ba, obj, caches) {
      switch (typeof obj) {
      case 'boolean':
        ba.writeByte(obj ? AMF3_TRUE_MARKER : AMF3_FALSE_MARKER);
        break;
      case 'number':
        if (obj === (obj | 0)) {
          ba.writeByte(AMF3_INTEGER_MARKER);
          writeU29(ba, obj);
        } else {
          ba.writeByte(AMF3_DOUBLE_MARKER);
          writeDouble(ba, obj);
        }
        break;
      case 'undefined':
        ba.writeByte(AMF3_UNDEFINED_MARKER);
        break;
      case 'string':
        ba.writeByte(AMF3_STRING_MARKER);
        writeUTF8vr(ba, obj, caches);
        break;
      case 'object':
        if (obj === null) {
          ba.writeByte(AMF3_NULL_MARKER);
        } else if (Array.isArray(obj)) {
          ba.writeByte(AMF3_ARRAY_MARKER);
          if (writeCachedReference(ba, obj, caches))
            break;
          var densePortionLength = 0;
          while (densePortionLength in obj) {
            ++densePortionLength;
          }
          writeU29(ba, densePortionLength << 1 | 1);
          forEachPublicProperty(obj, function (i, value) {
            if (isNumeric(i) && i >= 0 && i < densePortionLength) {
              return;
            }
            writeUTF8vr(ba, i, caches);
            writeAmf3Data(ba, value, caches);
          });
          writeUTF8vr(ba, '', caches);
          for (var j = 0; j < densePortionLength; j++) {
            writeAmf3Data(ba, obj[j], caches);
          }
        } else if (obj instanceof Date) {
          ba.writeByte(AMF3_DATE_MARKER);
          if (writeCachedReference(ba, obj, caches))
            break;
          writeU29(ba, 1);
          writeDouble(ba, obj.valueOf());
        } else {
          ba.writeByte(AMF3_OBJECT_MARKER);
          if (writeCachedReference(ba, obj, caches))
            break;
          var isDynamic = true;
          var objectClass = obj.class;
          if (objectClass) {
            isDynamic = !objectClass.classInfo.instanceInfo.isSealed();
            var aliasName = aliasesCache.classes.get(objectClass) || '';
            var traits, traitsCount;
            var traitsCache = caches.traitsCache || (caches.traitsCache = []);
            var traitsInfos = caches.traitsInfos || (caches.traitsInfos = []);
            var traitsRef = traitsCache.indexOf(objectClass);
            if (traitsRef < 0) {
              var slots = objectClass.instanceBindings.slots;
              traits = [];
              var traitsNames = [];
              for (var i = 1; i < slots.length; i++) {
                var slot = slots[i];
                if (!slot.name.getNamespace().isPublic()) {
                  continue;
                }
                traits.push(Multiname.getQualifiedName(slot.name));
                traitsNames.push(slot.name.name);
              }
              traitsCache.push(objectClass);
              traitsInfos.push(traits);
              traitsCount = traitsNames.length;
              writeU29(ba, (isDynamic ? 11 : 3) + (traitsCount << 4));
              writeUTF8vr(ba, aliasName, caches);
              for (var i = 0; i < traitsCount; i++) {
                writeUTF8vr(ba, traitsNames[i], caches);
              }
            } else {
              traits = traitsInfos[traitsRef];
              traitsCount = traits.length;
              writeU29(ba, 1 + (traitsRef << 2));
            }
            for (var i = 0; i < traitsCount; i++) {
              writeAmf3Data(ba, obj[traits[i]], caches);
            }
          } else {
            writeU29(ba, 11);
            writeUTF8vr(ba, '', caches);
          }
          if (isDynamic) {
            forEachPublicProperty(obj, function (i, value) {
              writeUTF8vr(ba, i, caches);
              writeAmf3Data(ba, value, caches);
            });
            writeUTF8vr(ba, '', caches);
          }
        }
        return;
      }
    }
    var aliasesCache = {
        classes: new WeakMap(),
        names: Object.create(null)
      };
    var amf3 = {
        write: function (ba, obj) {
          writeAmf3Data(ba, obj, {});
        },
        read: function (ba) {
          return readAmf3Data(ba, {});
        }
      };
    return {
      encodings: [
        amf0,
        null,
        null,
        amf3
      ],
      aliasesCache: aliasesCache
    };
  }();
function ProxyClass(runtime, scope, instanceConstructor, baseClass) {
  function ProxyConstructor() {
    somewhatImplemented('Proxy');
  }
  var c = new Class('Proxy', ProxyConstructor, ApplicationDomain.coerceCallable(ProxyConstructor));
  c.extendBuiltin(baseClass);
  return c;
}
var proxyTrapQns = {
    'getProperty': null,
    'setProperty': null,
    'hasProperty': null,
    'callProperty': null
  };
for (var name in proxyTrapQns) {
  proxyTrapQns[name] = VM_OPEN_METHOD_PREFIX + Multiname.getQualifiedName(new Multiname([
    ASNamespace.PROXY
  ], name));
}
function isProxyObject(obj) {
  return obj[VM_IS_PROXY];
}
function nameFromQualifiedName(qn) {
  if (isNumeric(qn)) {
    return qn;
  }
  var mn = Multiname.fromQualifiedName(qn);
  if (mn === undefined) {
    return undefined;
  }
  return mn.name;
}
function hasNonProxyingCaller() {
  var caller = arguments.callee;
  var maxDepth = 5;
  var domain;
  for (var i = 0; i < maxDepth && caller; i++) {
    if (caller === nonProxyingHasProperty) {
      return true;
    }
    caller = caller.caller;
  }
  return false;
}
function installProxyClassWrapper(cls) {
  var TRACE_PROXY = false;
  if (TRACE_PROXY) {
    print('proxy wrapping, class: ' + cls);
  }
  var instanceConstructor = cls.instanceConstructor;
  function construct() {
    if (TRACE_PROXY) {
      print('proxy create, class: ' + cls);
    }
    var target = Object.create(instanceConstructor.prototype);
    var proxy = Proxy.create({
        get: function (o, qn) {
          if (qn === VM_IS_PROXY) {
            TRACE_PROXY && print('proxy check');
            return true;
          }
          if (qn === VM_CALL_PROXY) {
            TRACE_PROXY && print('proxy get caller');
            return function apply(mn, receiver, args) {
              receiver = receiver ? target : null;
              if (TRACE_PROXY) {
                print('proxy call, class: ' + target.class + ', mn: ' + mn + 'hasNonProxyingCallerr: ' + hasNonProxyingCaller());
              }
              var resolved = Multiname.isQName(mn) ? mn : target.resolveMultinameProperty(mn.namespaces, mn.name, mn.flags);
              var qn = resolved ? Multiname.getQualifiedName(resolved) : Multiname.getPublicQualifiedName(mn.name);
              if (!nameInTraits(target, qn)) {
                return target[proxyTrapQns.callProperty](mn.name, args);
              }
              if (TRACE_PROXY) {
                TRACE_PROXY && print('> proxy pass through ' + resolved);
              }
              if (target.asOpenMethods && target.asOpenMethods[qn]) {
                return target.asOpenMethods[qn].apply(o, args);
              }
              return undefined;
            };
          }
          if (TRACE_PROXY) {
            print('proxy get, class: ' + target.class + ', qn: ' + qn + 'hasNonProxyingCallerr: ' + hasNonProxyingCaller());
          }
          if (!hasNonProxyingCaller()) {
            var name = nameFromQualifiedName(qn);
            if (name !== undefined && !nameInTraits(target, qn)) {
              return target[proxyTrapQns.getProperty](name);
            }
          }
          if (target.asOpenMethods && target.asOpenMethods[qn]) {
            return bindSafely(target.asOpenMethods[qn], o);
          }
          TRACE_PROXY && print('> proxy pass through ' + qn);
          return target[qn];
        },
        set: function (o, qn, value) {
          if (TRACE_PROXY) {
            print('proxy set, class: ' + target.class + ', qn: ' + qn + 'hasNonProxyingCallerr: ' + hasNonProxyingCaller());
          }
          if (!hasNonProxyingCaller()) {
            var name = nameFromQualifiedName(qn);
            if (name !== undefined && !nameInTraits(target, qn)) {
              target[proxyTrapQns.setProperty](name, value);
              return;
            }
          }
          TRACE_PROXY && print('> proxy pass through ' + qn);
          target[qn] = value;
        },
        has: function (qn) {
          if (TRACE_PROXY) {
            print('proxy has, class: ' + target.class + ', qn: ' + qn + 'hasNonProxyingCallerr: ' + hasNonProxyingCaller());
          }
          if (!hasNonProxyingCaller()) {
            var name = nameFromQualifiedName(qn);
            if (name !== undefined && !nameInTraits(target, qn)) {
              return target[proxyTrapQns.hasProperty](name);
            }
          }
          return qn in target;
        },
        hasOwn: function (qn) {
          if (TRACE_PROXY) {
            print('proxy hasOwn, class: ' + target.class + ', qn: ' + qn + 'hasNonProxyingCallerr: ' + hasNonProxyingCaller());
          }
          if (!hasNonProxyingCaller()) {
            var name = nameFromQualifiedName(qn);
            if (name !== undefined && !nameInTraits(target, qn)) {
              return target[proxyTrapQns.hasProperty](name);
            }
          }
          TRACE_PROXY && print('> proxy pass through ' + qn);
          return !(!Object.getOwnPropertyDescriptor(target, qn));
        },
        enumerate: function () {
          notImplemented('enumerate');
        },
        keys: function () {
          notImplemented('keys');
        }
      }, instanceConstructor.prototype);
    instanceConstructor.apply(proxy, sliceArguments(arguments, 0));
    return proxy;
  }
  cls.instanceConstructor = construct;
}
function DictionaryClass(domain, scope, instanceConstructor, baseClass) {
  function ASDictionary(weakKeys) {
    this.weakKeys = weakKeys;
    this.map = new WeakMap();
    if (!weakKeys) {
      this.keys = [];
    }
    this.primitiveMap = createEmptyObject();
  }
  var c = new Class('Dictionary', ASDictionary, ApplicationDomain.passthroughCallable(ASDictionary));
  c.extendNative(baseClass, ASDictionary);
  function makePrimitiveKey(key) {
    if (typeof key === 'string' || typeof key === 'number') {
      return key;
    }
    return undefined;
  }
  var prototype = ASDictionary.prototype;
  defineNonEnumerableProperty(prototype, 'asGetProperty', function asGetProperty(namespaces, name, flags, isMethod) {
    var key = makePrimitiveKey(name);
    if (key !== undefined) {
      return this.primitiveMap[key];
    }
    return this.map.get(Object(name));
  });
  defineNonEnumerableProperty(prototype, 'asGetResolvedStringProperty', asGetResolvedStringPropertyFallback);
  defineNonEnumerableProperty(prototype, 'asSetProperty', function asSetProperty(namespaces, name, flags, value) {
    var key = makePrimitiveKey(name);
    if (key !== undefined) {
      this.primitiveMap[key] = value;
      return;
    }
    this.map.set(Object(name), value);
    if (!this.weakKeys && this.keys.indexOf(name) < 0) {
      this.keys.push(name);
    }
  });
  defineNonEnumerableProperty(prototype, 'asCallProperty', function asCallProperty(namespaces, name, flags, isLex, args) {
    notImplemented('asCallProperty');
  });
  defineNonEnumerableProperty(prototype, 'asHasProperty', function asHasProperty(namespaces, name, flags, nonProxy) {
    var key = makePrimitiveKey(name);
    if (key !== undefined) {
      return key in this.primitiveMap;
    }
    return this.map.has(Object(name));
  });
  defineNonEnumerableProperty(prototype, 'asDeleteProperty', function asDeleteProperty(namespaces, name, flags) {
    var key = makePrimitiveKey(name);
    if (key !== undefined) {
      delete this.primitiveMap[key];
    }
    this.map.delete(Object(name));
    var i;
    if (!this.weakKeys && (i = this.keys.indexOf(name)) >= 0) {
      this.keys.splice(i, 1);
    }
    return true;
  });
  defineNonEnumerableProperty(prototype, 'asGetEnumerableKeys', function () {
    if (prototype === this) {
      return Object.prototype.asGetEnumerableKeys.call(this);
    }
    var primitiveMapKeys = [];
    for (var k in this.primitiveMap) {
      primitiveMapKeys.push(k);
    }
    if (this.weakKeys) {
      return primitiveMapKeys;
    }
    return primitiveMapKeys.concat(this.keys);
  });
  c.native = {
    instance: {
      init: function () {
      }
    }
  };
  return c;
}
function debugBreak(message) {
  debugger;
  print('\x1b[91mdebugBreak: ' + message + '\x1b[0m');
}
var NativeASNamespace;
var natives = function () {
    var C = ApplicationDomain.passthroughCallable;
    var CC = ApplicationDomain.constructingCallable;
    function ObjectClass(applicationDomain, scope, instanceConstructor, baseClass) {
      var c = new Class('Object', Object, C(Object));
      c.native = {
        instance: {
          isPrototypeOf: Object.prototype.isPrototypeOf,
          hasOwnProperty: function (name) {
            if (name === undefined) {
              return false;
            }
            name = Multiname.getPublicQualifiedName(name);
            if (Object.prototype.hasOwnProperty.call(this, name)) {
              return true;
            }
            return Object.getPrototypeOf(this).hasOwnProperty(name);
          },
          propertyIsEnumerable: function (name) {
            if (name === undefined) {
              return false;
            }
            name = Multiname.getPublicQualifiedName(name);
            return Object.prototype.propertyIsEnumerable.call(this, name);
          }
        },
        static: {
          _setPropertyIsEnumerable: function _setPropertyIsEnumerable(obj, name, isEnum) {
            name = Multiname.getPublicQualifiedName(name);
            var descriptor = Object.getOwnPropertyDescriptor(obj, name);
            descriptor.enumerable = false;
            Object.defineProperty(obj, name, descriptor);
          }
        }
      };
      c.dynamicPrototype = c.traitsPrototype = Object.prototype;
      c.setDefaultProperties();
      c.defaultValue = null;
      c.coerce = function (value) {
        return asCoerceObject(value);
      };
      c.isInstanceOf = function (value) {
        if (value === null) {
          return false;
        }
        return true;
      };
      c.isInstance = function (value) {
        if (value === null || value === undefined) {
          return false;
        }
        return true;
      };
      return c;
    }
    function ClassClass(runtime, scope, instanceConstructor, baseClass) {
      var c = Class;
      c.debugName = 'Class';
      c.prototype.extendBuiltin.call(c, baseClass);
      c.coerce = function (value) {
        return value;
      };
      c.isInstanceOf = function (value) {
        return true;
      };
      c.isInstance = function (value) {
        return value instanceof c.instanceConstructor;
      };
      return c;
    }
    function BooleanClass(runtime, scope, instanceConstructor, baseClass) {
      var c = new Class('Boolean', Boolean, C(Boolean));
      c.extendBuiltin(baseClass);
      c.native = {
        instance: {
          toString: Boolean.prototype.toString,
          valueOf: Boolean.prototype.valueOf
        }
      };
      c.coerce = Boolean;
      c.isInstanceOf = function (value) {
        return typeof value === 'boolean' || value instanceof Boolean;
      };
      c.isInstance = function (value) {
        if (typeof value === 'boolean' || value instanceof Boolean) {
          return true;
        }
        return false;
      };
      return c;
    }
    function FunctionClass(runtime, scope, instanceConstructor, baseClass) {
      var c = new Class('Function', Function, C(Function));
      c.extendBuiltin(baseClass);
      c.native = {
        instance: {
          prototype: {
            get: function () {
              return this.prototype;
            },
            set: function (p) {
              this.prototype = p;
            }
          },
          length: {
            get: function () {
              if (this.hasOwnProperty(VM_LENGTH)) {
                return this.asLength;
              }
              return this.length;
            }
          },
          call: Function.prototype.call,
          apply: Function.prototype.apply
        }
      };
      c.coerce = function (value) {
        return value;
      };
      c.isInstanceOf = function (value) {
        return typeof value === 'function';
      };
      c.isInstance = function (value) {
        return typeof value === 'function';
      };
      return c;
    }
    function MethodClosure($this, fn) {
      var bound = bindSafely(fn, $this);
      defineNonEnumerableProperty(this, 'call', bound.call.bind(bound));
      defineNonEnumerableProperty(this, 'apply', bound.apply.bind(bound));
    }
    MethodClosure.prototype = {
      toString: function () {
        return 'function Function() {}';
      }
    };
    function MethodClosureClass(runtime, scope, instanceConstructor, baseClass) {
      var c = new Class('MethodClosure', MethodClosure);
      c.extendBuiltin(baseClass);
      return c;
    }
    function StringClass(runtime, scope, instanceConstructor, baseClass) {
      var c = new Class('String', String, C(String));
      c.extendBuiltin(baseClass);
      var Sp = String.prototype;
      c.native = {
        instance: {
          length: {
            get: function () {
              return this.length;
            }
          },
          indexOf: Sp.indexOf,
          lastIndexOf: Sp.lastIndexOf,
          charAt: Sp.charAt,
          charCodeAt: Sp.charCodeAt,
          concat: Sp.concat,
          localeCompare: Sp.localeCompare,
          match: function (re) {
            if (re === void 0 || re === null) {
              return null;
            } else {
              if (re instanceof RegExp && re.global) {
                var matches = [], m;
                while (m = re.exec(this)) {
                  matches.push(m[0]);
                }
                return matches;
              }
              if (!(re instanceof RegExp) && !(typeof re === 'string')) {
                re = String(re);
              }
              return this.match(re);
            }
          },
          replace: Sp.replace,
          search: function (re) {
            if (re === void 0) {
              return -1;
            } else {
              return this.search(re);
            }
          },
          slice: Sp.slice,
          split: Sp.split,
          substr: Sp.substr,
          substring: Sp.substring,
          toLowerCase: Sp.toLowerCase,
          toLocaleLowerCase: Sp.toLocaleLowerCase,
          toUpperCase: function () {
            var str = Sp.toUpperCase.apply(this);
            var str = str.replace(/\u039C/g, String.fromCharCode(181));
            return str;
          },
          toLocaleUpperCase: function () {
            var str = Sp.toLocaleUpperCase.apply(this);
            var str = str.replace(/\u039C/g, String.fromCharCode(181));
            return str;
          },
          toString: Sp.toString,
          valueOf: Sp.valueOf
        },
        static: String
      };
      c.isInstance = function (value) {
        return value !== null && value !== undefined && typeof value.valueOf() === 'string';
      };
      c.coerce = function (value) {
        if (value === null || value === undefined) {
          return null;
        }
        return String(value);
      };
      c.isInstanceOf = function (value) {
        return Object(value) instanceof String;
      };
      c.isInstance = function (value) {
        return Object(value) instanceof String;
      };
      return c;
    }
    function VectorClass(domain, scope, instanceConstructor, baseClass) {
      return createVectorClass(undefined, baseClass);
    }
    function ObjectVectorClass(domain, scope, instanceConstructor, baseClass) {
      return createVectorClass(domain.getClass('Object'), baseClass);
    }
    function IntVectorClass(domain, scope, instanceConstructor, baseClass) {
      return createVectorClass(domain.getClass('int'), baseClass);
    }
    function UIntVectorClass(domain, scope, instanceConstructor, baseClass) {
      return createVectorClass(domain.getClass('uint'), baseClass);
    }
    function DoubleVectorClass(domain, scope, instanceConstructor, baseClass) {
      return createVectorClass(domain.getClass('Number'), baseClass);
    }
    function createVectorClass(type, baseClass) {
      var V;
      if (type) {
        var className = 'Vector$' + type.classInfo.instanceInfo.name.name;
        switch (className) {
        case 'Vector$int':
          V = Int32Vector;
          break;
        case 'Vector$uint':
          V = Uint32Vector;
          break;
        case 'Vector$Number':
          V = Float64Vector;
          break;
        case 'Vector$Object':
          V = GenericVector;
          break;
        default:
          unexpected();
          break;
        }
      } else {
        V = GenericVector.applyType(null);
      }
      var Vp = V.prototype;
      var cls = new Class(className, V, C(V.callable));
      if (V === GenericVector) {
        cls.applyType = function (type) {
          return cls;
        };
      }
      cls.extendWrapper(baseClass, V);
      cls.native = {
        instance: {
          fixed: {
            get: function () {
              return this._fixed;
            },
            set: function (v) {
              this._fixed = v;
            }
          },
          length: {
            get: function () {
              return this.length;
            },
            set: function setLength(length) {
              this.length = length;
            }
          },
          push: Vp.push,
          pop: Vp.pop,
          shift: Vp.shift,
          unshift: Vp.unshift,
          _reverse: Vp.reverse,
          _filter: Vp.filter,
          _map: Vp.map,
          newThisType: function newThisType() {
            return new cls.instanceConstructor();
          },
          _spliceHelper: function _spliceHelper(insertPoint, insertCount, deleteCount, args, offset) {
            return this._spliceHelper(insertPoint, insertCount, deleteCount, args, offset);
          }
        },
        static: {
          _some: function (o, callback, thisObject) {
            return o.some(callback, thisObject);
          },
          _every: function (o, callback, thisObject) {
            return o.every(callback, thisObject);
          },
          _forEach: function (o, callback, thisObject) {
            return o.forEach(callback, thisObject);
          },
          _sort: arraySort
        }
      };
      cls.vectorType = type;
      cls.coerce = function (value) {
        return value;
      };
      cls.isInstanceOf = function (value) {
        return true;
      };
      cls.isInstance = function (value) {
        if (value === null || typeof value !== 'object') {
          return false;
        }
        if (!this.instanceConstructor.vectorType && value.class.vectorType) {
          return true;
        }
        return this.instanceConstructor.prototype.isPrototypeOf(value);
      };
      return cls;
    }
    function NumberClass(runtime, scope, instanceConstructor, baseClass) {
      var c = new Class('Number', Number, C(Number));
      c.extendBuiltin(baseClass);
      c.native = {
        instance: Number.prototype
      };
      c.defaultValue = Number(0);
      c.isInstance = function (value) {
        return value !== null && value !== undefined && typeof value.valueOf() === 'number';
      };
      c.coerce = Number;
      c.isInstanceOf = function (value) {
        return Object(value) instanceof Number;
      };
      c.isInstance = function (value) {
        return Object(value) instanceof Number;
      };
      return c;
    }
    function Int(x) {
      return x | 0;
    }
    function boxedInt(x) {
      return Object(x | 0);
    }
    function intClass(runtime, scope, instanceConstructor, baseClass) {
      var c = new Class('int', boxedInt, C(Int));
      c.extendBuiltin(baseClass);
      c.defaultValue = 0;
      c.coerce = Int;
      c.isInstanceOf = function (value) {
        return false;
      };
      c.isInstance = function (value) {
        if (value instanceof Number) {
          value = value.valueOf();
        }
        return (value | 0) === value;
      };
      return c;
    }
    function Uint(x) {
      return x >>> 0;
    }
    function boxedUint(x) {
      return Object(x >>> 0);
    }
    function uintClass(runtime, scope, instanceConstructor, baseClass) {
      var c = new Class('uint', boxedUint, C(Uint));
      c.extend(baseClass);
      c.defaultValue = 0;
      c.isInstanceOf = function (value) {
        return false;
      };
      c.isInstance = function (value) {
        if (value instanceof Number) {
          value = value.valueOf();
        }
        return value >>> 0 === value;
      };
      c.coerce = Uint;
      return c;
    }
    function MathClass(runtime, scope, instanceConstructor, baseClass) {
      var c = new Class('Math');
      c.native = {
        static: Math
      };
      return c;
    }
    function DateClass(runtime, scope, instanceConstructor, baseClass) {
      var c = new Class('Date', Date, C(Date));
      c.extendBuiltin(baseClass);
      c.native = {
        instance: Date.prototype,
        static: Date
      };
      return c;
    }
    function makeErrorClass(name) {
      var ErrorDefinition = {
          __glue__: {
            script: {
              instance: {
                message: 'public message',
                name: 'public name'
              }
            },
            native: {
              instance: {
                getStackTrace: function () {
                  somewhatImplemented('Error.getStackTrace()');
                  return AVM2.getStackTrace();
                }
              },
              static: {
                getErrorMessage: getErrorMessage
              }
            }
          }
        };
      return function (runtime, scope, instanceConstructor, baseClass) {
        var c = new Class(name, instanceConstructor);
        c.extend(baseClass);
        if (name === 'Error') {
          c.link(ErrorDefinition);
          c.linkNatives(ErrorDefinition);
        }
        return c;
      };
    }
    function RegExpClass(runtime, scope, instanceConstructor, baseClass) {
      var c = new Class('RegExp', XRegExp, C(XRegExp));
      c.extendBuiltin(baseClass);
      RegExpClass.exec = function exec() {
        var result = this.exec.apply(this, arguments);
        if (!result) {
          return result;
        }
        var keys = Object.keys(result);
        for (var i = 0; i < keys.length; i++) {
          var k = keys[i];
          if (!isNumeric(k)) {
            if (result[k] === undefined) {
              result[k] = '';
            }
          }
        }
        publicizeProperties(result);
        return result;
      };
      RegExpClass.test = function test() {
        return this.exec.apply(this, arguments) !== null;
      };
      c.native = {
        instance: {
          global: {
            get: function () {
              return this.global;
            }
          },
          source: {
            get: function () {
              return this.source;
            }
          },
          ignoreCase: {
            get: function () {
              return this.ignoreCase;
            }
          },
          multiline: {
            get: function () {
              return this.multiline;
            }
          },
          lastIndex: {
            get: function () {
              return this.lastIndex;
            },
            set: function (i) {
              this.lastIndex = i;
            }
          },
          dotall: {
            get: function () {
              return this.dotall;
            }
          },
          extended: {
            get: function () {
              return this.extended;
            }
          },
          exec: RegExpClass.exec,
          test: RegExpClass.test
        }
      };
      return c;
    }
    function NamespaceClass(runtime, scope, instanceConstructor, baseClass) {
      NativeASNamespace = function NativeASNamespace(prefixValue, uriValue) {
        if (uriValue === undefined) {
          uriValue = prefixValue;
          prefixValue = undefined;
        }
        var prefix, uri;
        if (prefixValue === undefined) {
          if (uriValue === undefined) {
            prefix = '';
            uri = '';
          } else if (typeof uriValue === 'object') {
            prefix = uriValue.prefix;
            if (uriValue instanceof ASNamespace) {
              uri = uriValue.uri;
            } else if (uriValue instanceof QName) {
              uri = uriValue.uri;
            }
          } else {
            uri = uriValue + '';
            if (uri === '') {
              prefix = '';
            } else {
              prefix = undefined;
            }
          }
        } else {
          if (typeof uriValue === 'object' && uriValue instanceof QName && uriValue.uri !== null) {
            uri = uriValue.uri;
          } else {
            uri = uriValue + '';
          }
          if (uri === '') {
            if (prefixValue === undefined || prefixValue + '' === '') {
              prefix = '';
            } else {
              throw 'type error';
            }
          } else if (prefixValue === undefined || prefixValue === '') {
            prefix = undefined;
          } else if (false && !isXMLName(prefixValue)) {
            prefix = undefined;
          } else {
            prefix = prefixValue + '';
          }
        }
        return ASNamespace.createNamespace(uri, prefix);
      };
      var c = new Class('Namespace', NativeASNamespace, C(NativeASNamespace));
      c.extendNative(baseClass, ASNamespace);
      var Np = ASNamespace.prototype;
      c.native = {
        instance: {
          prefix: {
            get: Np.getPrefix
          },
          uri: {
            get: Np.getURI
          }
        }
      };
      return c;
    }
    function JSONClass(runtime, scope, instanceConstructor, baseClass) {
      function transformJSValueToAS(value) {
        if (typeof value !== 'object') {
          return value;
        }
        var keys = Object.keys(value);
        var result = value instanceof Array ? [] : {};
        for (var i = 0; i < keys.length; i++) {
          result.asSetPublicProperty(keys[i], transformJSValueToAS(value[keys[i]]));
        }
        return result;
      }
      function transformASValueToJS(value) {
        if (typeof value !== 'object') {
          return value;
        }
        var keys = Object.keys(value);
        var result = value instanceof Array ? [] : {};
        for (var i = 0; i < keys.length; i++) {
          var key = keys[i];
          var jsKey = key;
          if (!isNumeric(key)) {
            jsKey = Multiname.getNameFromPublicQualifiedName(key);
          }
          result[jsKey] = transformASValueToJS(value[key]);
        }
        return result;
      }
      function ASJSON() {
      }
      var c = new Class('JSON', ASJSON, C(ASJSON));
      c.extend(baseClass);
      c.native = {
        static: {
          parseCore: function parseCore(text) {
            return transformJSValueToAS(JSON.parse(text));
          },
          stringifySpecializedToString: function stringifySpecializedToString(value, replacerArray, replacerFunction, gap) {
            return JSON.stringify(transformASValueToJS(value), replacerFunction, gap);
          }
        }
      };
      return c;
    }
    function CapabilitiesClass(runtime, scope, instanceConstructor, baseClass) {
      function Capabilities() {
      }
      var c = new Class('Capabilities', Capabilities, C(Capabilities));
      c.extend(baseClass);
      c.native = {
        static: {
          playerType: {
            get: function () {
              return 'AVMPlus';
            }
          }
        }
      };
      return c;
    }
    function FileClass(runtime, scope, instanceConstructor, baseClass) {
      function File() {
      }
      var c = new Class('File', File, C(File));
      c.extend(baseClass);
      c.native = {
        static: {
          exists: function (filename) {
            notImplemented('File.exists');
            return false;
          },
          read: function (filename) {
            return snarf(filename);
          },
          write: function (filename, data) {
            notImplemented('File.write');
            return true;
          },
          readByteArray: function (filename) {
            var ByteArrayClass = AVM2.currentDomain().getClass('flash.utils.ByteArray');
            var data = ByteArrayClass.createInstance();
            data.writeRawBytes(snarf(filename, 'binary'));
            return data;
          },
          writeByteArray: function (filename, bytes) {
            write('bin/' + filename, bytes.getBytes());
            return true;
          }
        }
      };
      return c;
    }
    function ShumwayClass(runtime, scope, instanceConstructor, baseClass) {
      function Shumway() {
      }
      var c = new Class('Shumway', Shumway, C(Shumway));
      c.extend(baseClass);
      c.native = {
        static: {
          info: function (x) {
            console.info(x);
          },
          json: function (x) {
            return JSON.stringify(x);
          },
          eval: function (x) {
            return eval(x);
          },
          debugger: function (x) {
            debugger;
          }
        }
      };
      return c;
    }
    function constant(x) {
      return function () {
        return x;
      };
    }
    function ByteArrayClass(runtime, scope, instanceConstructor, baseClass) {
      var BA = function () {
        ByteArray.call(this);
      };
      var BAp = BA.prototype = Object.create(ByteArray.prototype);
      var c = new Class('ByteArray', BA, C(BA));
      c.extendBuiltin(baseClass);
      BAp.asGetNumericProperty = function (i) {
        if (i >= this.length) {
          return undefined;
        }
        return this.uint8v[i];
      };
      BAp.asSetNumericProperty = function (i, v) {
        var len = i + 1;
        this.ensureCapacity(len);
        this.uint8v[i] = v;
        if (len > this.length) {
          this.length = len;
        }
      };
      BAp.readUTF = function readUTF() {
        return this.readUTFBytes(this.readShort());
      };
      BAp.readUTFBytes = function readUTFBytes(length) {
        var pos = this.position;
        if (pos + length > this.length) {
          throwEOFError();
        }
        this.position += length;
        return utf8encode(new Int8Array(this.a, pos, length));
      };
      BAp.writeUTF = function writeUTF(str) {
        var bytes = utf8decode(str);
        this.writeShort(bytes.length);
        this.writeRawBytes(bytes);
      };
      BAp.writeUTFBytes = function writeUTFBytes(str) {
        var bytes = utf8decode(str);
        this.writeRawBytes(bytes);
      };
      BAp.toString = function toString() {
        return utf8encode(new Int8Array(this.a, 0, this.length));
      };
      c.native = {
        instance: {
          length: {
            get: function () {
              return this.length;
            },
            set: function setLength(length) {
              var cap = this.a.byteLength;
              if (length > cap) {
                this.ensureCapacity(length);
              }
              this.length = length;
              this.position = clamp(this.position, 0, this.length);
            }
          },
          bytesAvailable: {
            get: function () {
              return this.length - this.position;
            }
          },
          position: {
            get: function () {
              return this.position;
            },
            set: function (p) {
              this.position = p;
            }
          },
          endian: {
            get: function () {
              return this.le ? 'littleEndian' : 'bigEndian';
            },
            set: function (e) {
              this.le = e === 'littleEndian';
            }
          },
          objectEncoding: {
            get: function () {
              return this.objectEncoding;
            },
            set: function (v) {
              this.objectEncoding = v;
            }
          },
          writeBytes: BAp.writeBytes,
          writeBoolean: BAp.writeBoolean,
          writeByte: BAp.writeByte,
          writeShort: BAp.writeShort,
          writeInt: BAp.writeInt,
          writeUnsignedInt: BAp.writeUnsignedInt,
          writeFloat: BAp.writeFloat,
          writeDouble: BAp.writeDouble,
          writeMultiByte: BAp.writeMultiByte,
          writeObject: function writeObject(v) {
            return AMFUtils.encodings[this.objectEncoding].write(this, v);
          },
          writeUTF: BAp.writeUTF,
          writeUTFBytes: BAp.writeUTFBytes,
          readBoolean: BAp.readBoolean,
          readByte: BAp.readByte,
          readBytes: BAp.readBytes,
          readUnsignedByte: BAp.readUnsignedByte,
          readShort: BAp.readShort,
          readUnsignedShort: BAp.readUnsignedShort,
          readInt: BAp.readInt,
          readUnsignedInt: BAp.readUnsignedInt,
          readFloat: BAp.readFloat,
          readDouble: BAp.readDouble,
          readMultiByte: BAp.readMultiByte,
          readObject: function readObject() {
            return AMFUtils.encodings[this.objectEncoding].read(this);
          },
          readUTF: BAp.readUTF,
          readUTFBytes: BAp.readUTFBytes,
          toString: BAp.toString,
          clear: BAp.clear,
          _compress: BAp.compress,
          _uncompress: BAp.uncompress
        },
        static: {
          defaultObjectEncoding: {
            get: function () {
              return ByteArray.DEFAULT_OBJECT_ENCODING;
            },
            set: function (e) {
              ByteArray.DEFAULT_OBJECT_ENCODING = e;
            }
          }
        }
      };
      return c;
    }
    function DomainClass(runtime, scope, instanceConstructor, baseClass) {
      var c = new Class('File', instanceConstructor, C(instanceConstructor));
      c.extend(baseClass);
      c.native = {
        instance: {
          init: function (base) {
            this.base = base;
            this.nativeObject = new ApplicationDomain(AVM2.instance, base ? base.nativeObject : null);
          },
          loadBytes: function (byteArray, swfVersion) {
            this.nativeObject.executeAbc(new AbcFile(byteArray.readRawBytes()));
          },
          getClass: function (className) {
            return this.nativeObject.getClass(className);
          }
        },
        static: {
          currentDomain: {
            get: function () {
              var domain = Object.create(instanceConstructor.prototype);
              domain.nativeObject = AVM2.currentDomain();
              return domain;
            }
          }
        }
      };
      return c;
    }
    function SystemClass(runtime, scope, instanceConstructor, baseClass) {
      var c = new Class('System', instanceConstructor, C(instanceConstructor));
      c.extend(baseClass);
      c.native = {
        static: {
          swfVersion: {
            get: function () {
              return 19;
            }
          },
          apiVersion: {
            get: function () {
              return 26;
            }
          },
          getArgv: function () {
            return [];
          },
          getRunmode: function () {
            return 'mixed';
          }
        }
      };
      return c;
    }
    function bugzilla(n) {
      switch (n) {
      case 574600:
        return true;
      }
      return false;
    }
    return {
      print: constant(print),
      notImplemented: constant(notImplemented),
      debugBreak: constant(debugBreak),
      bugzilla: constant(bugzilla),
      decodeURI: constant(decodeURI),
      decodeURIComponent: constant(decodeURIComponent),
      encodeURI: constant(encodeURI),
      encodeURIComponent: constant(encodeURIComponent),
      isNaN: constant(isNaN),
      isFinite: constant(isFinite),
      parseInt: constant(parseInt),
      parseFloat: constant(parseFloat),
      escape: constant(escape),
      unescape: constant(unescape),
      isXMLName: constant(typeof isXMLName !== 'undefined' ? isXMLName : function () {
        notImplemented('Chrome doesn\'t support isXMLName.');
      }),
      Function: Function,
      String: String,
      Array: Array,
      Number: Number,
      Boolean: Boolean,
      Math: Math,
      Date: Date,
      RegExp: RegExp,
      Object: Object,
      ObjectClass: ObjectClass,
      Class: ClassClass,
      NamespaceClass: NamespaceClass,
      FunctionClass: FunctionClass,
      MethodClosureClass: MethodClosureClass,
      BooleanClass: BooleanClass,
      StringClass: StringClass,
      NumberClass: NumberClass,
      intClass: intClass,
      uintClass: uintClass,
      ArrayClass: ArrayClass,
      VectorClass: VectorClass,
      ObjectVectorClass: ObjectVectorClass,
      IntVectorClass: IntVectorClass,
      UIntVectorClass: UIntVectorClass,
      DoubleVectorClass: DoubleVectorClass,
      ByteArrayClass: ByteArrayClass,
      ProxyClass: ProxyClass,
      ErrorClass: makeErrorClass('Error'),
      DefinitionErrorClass: makeErrorClass('DefinitionError'),
      EvalErrorClass: makeErrorClass('EvalError'),
      RangeErrorClass: makeErrorClass('RangeError'),
      ReferenceErrorClass: makeErrorClass('ReferenceError'),
      SecurityErrorClass: makeErrorClass('SecurityError'),
      SyntaxErrorClass: makeErrorClass('SyntaxError'),
      TypeErrorClass: makeErrorClass('TypeError'),
      URIErrorClass: makeErrorClass('URIError'),
      VerifyErrorClass: makeErrorClass('VerifyError'),
      UninitializedErrorClass: makeErrorClass('UninitializedError'),
      ArgumentErrorClass: makeErrorClass('ArgumentError'),
      DateClass: DateClass,
      MathClass: MathClass,
      RegExpClass: RegExpClass,
      DictionaryClass: DictionaryClass,
      XMLClass: XMLClass,
      XMLListClass: XMLListClass,
      QNameClass: QNameClass,
      JSONClass: JSONClass,
      ShumwayClass: ShumwayClass,
      CapabilitiesClass: CapabilitiesClass,
      FileClass: FileClass,
      DomainClass: DomainClass,
      SystemClass: SystemClass,
      getQualifiedClassName: constant(function (value) {
        if (value === null) {
          return 'null';
        } else if (value === undefined) {
          return 'void';
        }
        switch (typeof value) {
        case 'number':
          if ((value | 0) === value) {
            return 'int';
          }
          return 'Number';
        case 'string':
          return 'String';
        case 'boolean':
          return 'Boolean';
        case 'object':
          if (value instanceof Date) {
            return 'Date';
          }
          var cls;
          if (value instanceof Class) {
            cls = value;
          } else if (value.class) {
            cls = value.class;
          } else if (value.classInfo) {
            cls = value;
          }
          if (cls) {
            var name = cls.classInfo.instanceInfo.name;
            var uri = name.namespaces[0].uri;
            if (uri) {
              return uri + '::' + name.name;
            }
            return name.name;
          }
          break;
        }
        return notImplemented(value + ' (' + typeof value + ')');
      }),
      getQualifiedSuperclassName: constant(function (value) {
        switch (typeof value) {
        case 'number':
        case 'string':
        case 'boolean':
          return 'Object';
        case 'function':
          return 'Function';
        case 'object':
          if (value instanceof Date) {
            return 'Object';
          }
          var cls;
          if (value.class) {
            cls = value.class;
          } else if (value.classInfo) {
            cls = value;
          }
          if (cls && cls.baseClass) {
            var name = cls.baseClass.classInfo.instanceInfo.name;
            var uri = name.namespaces[0].uri;
            if (uri) {
              return uri + '::' + name.name;
            }
            return name.name;
          }
          return 'Object';
        }
        return notImplemented(value + ' (superOf ' + typeof value + ')');
      }),
      getDefinitionByName: constant(function (name) {
        var simpleName = String(name).replace('::', '.');
        return AVM2.currentDomain().getClass(simpleName);
      }),
      describeTypeJSON: constant(describeTypeJSON),
      original: jsGlobal[VM_NATIVE_BUILTIN_ORIGINALS]
    };
    function describeTypeJSON(o, flags) {
      var Flags = {
          HIDE_NSURI_METHODS: 1,
          INCLUDE_BASES: 2,
          INCLUDE_INTERFACES: 4,
          INCLUDE_VARIABLES: 8,
          INCLUDE_ACCESSORS: 16,
          INCLUDE_METHODS: 32,
          INCLUDE_METADATA: 64,
          INCLUDE_CONSTRUCTOR: 128,
          INCLUDE_TRAITS: 256,
          USE_ITRAITS: 512,
          HIDE_OBJECT: 1024
        };
      var declaredByKey = publicName('declaredBy');
      var metadataKey = publicName('metadata');
      var accessKey = publicName('access');
      var uriKey = publicName('uri');
      var nameKey = publicName('name');
      var typeKey = publicName('type');
      var returnTypeKey = publicName('returnType');
      var valueKey = publicName('value');
      var keyKey = publicName('key');
      var parametersKey = publicName('parameters');
      var optionalKey = publicName('optional');
      var cls = o.classInfo ? o : Object.getPrototypeOf(o).class;
      true;
      var info = cls.classInfo;
      var description = {};
      description[nameKey] = unmangledQualifiedName(info.instanceInfo.name);
      description[publicName('isDynamic')] = cls === o ? true : !(info.instanceInfo.flags & CONSTANT_ClassSealed);
      description[publicName('isStatic')] = cls === o;
      description[publicName('isFinal')] = cls === o ? true : !(info.instanceInfo.flags & CONSTANT_ClassFinal);
      if (flags & Flags.INCLUDE_TRAITS) {
        description[publicName('traits')] = addTraits(cls, flags);
      }
      var metadata = null;
      if (info.metadata) {
        metadata = Object.keys(info.metadata).map(function (key) {
          return describeMetadata(info.metadata[key]);
        });
      }
      description[metadataKey] = metadata;
      return description;
      function publicName(str) {
        return Multiname.getPublicQualifiedName(str);
      }
      function unmangledQualifiedName(mn) {
        var name = mn.name;
        var namespace = mn.namespaces[0];
        if (namespace && namespace.uri) {
          return namespace.uri + '::' + name;
        }
        return name;
      }
      function describeMetadata(metadata) {
        var result = {};
        result[nameKey] = metadata.name;
        result[valueKey] = metadata.value.map(function (value) {
          var val = {};
          val[keyKey] = value.key;
          val[valueKey] = value.value;
          return value;
        });
        return result;
      }
      function addTraits(cls, flags) {
        var includedMembers = [
            flags & Flags.INCLUDE_VARIABLES,
            flags & Flags.INCLUDE_METHODS,
            flags & Flags.INCLUDE_ACCESSORS,
            flags & Flags.INCLUDE_ACCESSORS
          ];
        var includeBases = flags & Flags.INCLUDE_BASES;
        var includeMetadata = flags & Flags.INCLUDE_METADATA;
        var obj = {};
        var basesVal = obj[publicName('bases')] = includeBases ? [] : null;
        if (flags & Flags.INCLUDE_INTERFACES) {
          var interfacesVal = obj[publicName('interfaces')] = [];
          if (flags & Flags.USE_ITRAITS) {
            for (var key in cls.implementedInterfaces) {
              var ifaceName = cls.implementedInterfaces[key].name;
              interfacesVal.push(unmangledQualifiedName(ifaceName));
            }
          }
        } else {
          obj[publicName('interfaces')] = null;
        }
        var variablesVal = obj[publicName('variables')] = flags & Flags.INCLUDE_VARIABLES ? [] : null;
        var accessorsVal = obj[publicName('accessors')] = flags & Flags.INCLUDE_ACCESSORS ? [] : null;
        var methodsVal = obj[publicName('methods')] = flags & Flags.INCLUDE_METHODS ? [] : null;
        var encounteredAccessors = {};
        var addBase = false;
        while (cls) {
          var className = unmangledQualifiedName(cls.classInfo.instanceInfo.name);
          if (includeBases && addBase) {
            basesVal.push(className);
          } else {
            addBase = true;
          }
          if (flags & Flags.USE_ITRAITS) {
            describeTraits(cls.classInfo.instanceInfo.traits);
          } else {
            describeTraits(cls.classInfo.traits);
          }
          cls = cls.baseClass;
        }
        function describeTraits(traits) {
          true;
          for (var i = 0; traits && i < traits.length; i++) {
            var t = traits[i];
            if (!includedMembers[t.kind] || !t.name.getNamespace().isPublic() && !t.name.uri) {
              continue;
            }
            var name = unmangledQualifiedName(t.name);
            if (encounteredAccessors[name]) {
              var val = encounteredAccessors[name];
              val[accessKey] = 'readwrite';
              if (t.kind === TRAIT_Getter) {
                val[typeKey] = unmangledQualifiedName(t.methodInfo.returnType);
              }
              continue;
            }
            var val = {};
            if (includeMetadata && t.metadata) {
              var metadataVal = val[metadataKey] = [];
              for (var key in t.metadata) {
                metadataVal.push(describeMetadata(t.metadata[key]));
              }
            } else {
              val[metadataKey] = null;
            }
            val[declaredByKey] = className;
            val[uriKey] = t.name.uri === undefined ? null : t.name.uri;
            val[nameKey] = name;
            if (!t.typeName && !(t.methodInfo && t.methodInfo.returnType)) {
              continue;
            }
            val[t.kind === TRAIT_Method ? returnTypeKey : typeKey] = unmangledQualifiedName(t.kind === TRAIT_Slot ? t.typeName : t.methodInfo.returnType);
            switch (t.kind) {
            case TRAIT_Slot:
              val[accessKey] = 'readwrite';
              variablesVal.push(val);
              break;
            case TRAIT_Method:
              var parametersVal = val[parametersKey] = [];
              var parameters = t.methodInfo.parameters;
              for (var j = 0; j < parameters.length; j++) {
                var param = parameters[j];
                var paramVal = {};
                paramVal[typeKey] = param.type ? unmangledQualifiedName(param.type) : '*';
                paramVal[optionalKey] = 'value' in param;
                parametersVal.push(paramVal);
              }
              methodsVal.push(val);
              break;
            case TRAIT_Getter:
            case TRAIT_Setter:
              val[accessKey] = t.kind === TRAIT_Getter ? 'read' : 'write';
              accessorsVal.push(val);
              encounteredAccessors[name] = val;
              break;
            default:
              break;
            }
          }
        }
        return obj;
      }
    }
  }();
function getNative(path) {
  var chain = path.split('.');
  var v = natives;
  for (var i = 0, j = chain.length; i < j; i++) {
    v = v && v[chain[i]];
  }
  true;
  return v;
}
var disassemblerOptions = systemOptions.register(new OptionSet('Disassembler Options'));
var filter = disassemblerOptions.register(new Option('f', 'filter', 'string', 'SpciMsmNtu', '[S]ource, constant[p]ool, [c]lasses, [i]nstances, [M]etadata, [s]cripts, [m]ethods, multi[N]ames, S[t]atistics, [u]tf'));
function traceArray(writer, name, array, abc) {
  if (array.length === 0) {
    return;
  }
  writer.enter(name + ' {');
  array.forEach(function (a, idx) {
    a.trace(writer, abc);
  });
  writer.leave('}');
}
AbcFile.prototype.trace = function trace(writer) {
  if (filter.value.indexOf('p') >= 0) {
    this.constantPool.trace(writer);
  }
  if (filter.value.indexOf('N') >= 0) {
    this.constantPool.traceMultinamesOnly(writer);
  }
  if (filter.value.indexOf('c') >= 0) {
    traceArray(writer, 'classes', this.classes);
  }
  if (filter.value.indexOf('i') >= 0) {
    traceArray(writer, 'instances', this.instances);
  }
  if (filter.value.indexOf('M') >= 0) {
    traceArray(writer, 'metadata', this.metadata);
  }
  if (filter.value.indexOf('s') >= 0) {
    traceArray(writer, 'scripts', this.scripts);
  }
  if (filter.value.indexOf('m') >= 0) {
    traceArray(writer, 'methods', this.methods, this);
  }
  if (filter.value.indexOf('S') >= 0) {
    traceSource(writer, this);
  }
  if (filter.value.indexOf('t') >= 0) {
    traceStatistics(writer, this);
  }
  if (filter.value.indexOf('u') >= 0) {
    print(JSON.stringify({
      strings: this.constantPool.strings,
      positionAfterUTFStrings: this.constantPool.positionAfterUTFStrings
    }, null, 2));
  }
};
ConstantPool.prototype.trace = function (writer) {
  writer.enter('constantPool {');
  for (var key in this) {
    if (key === 'namespaces') {
      writer.enter('namespaces {');
      this.namespaces.forEach(function (ns, i) {
        writer.writeLn(('' + i).padRight(' ', 3) + (ns ? ns.toString() : '*'));
      });
      writer.leave('}');
    } else if (this[key] instanceof Array) {
      writer.enter(key + ' ' + this[key].length + ' {');
      writer.writeArray(this[key]);
      writer.leave('}');
    }
  }
  writer.leave('}');
};
ConstantPool.prototype.traceMultinamesOnly = function (writer) {
  writer.writeArray(this.multinames, null, true);
};
ClassInfo.prototype.trace = function (writer) {
  writer.enter('class ' + this + ' {');
  traceArray(writer, 'traits', this.traits);
  writer.leave('}');
};
MetaDataInfo.prototype.trace = function (writer) {
  writer.enter(this + ' {');
  this.value.forEach(function (item) {
    writer.writeLn((item.key ? item.key + ': ' : '') + '"' + item.value + '"');
  });
  writer.leave('}');
};
InstanceInfo.prototype.trace = function (writer) {
  writer.enter('instance ' + this + ' {');
  traceArray(writer, 'traits', this.traits);
  writer.leave('}');
};
ScriptInfo.prototype.trace = function (writer) {
  writer.enter('script ' + this + ' {');
  traceArray(writer, 'traits', this.traits);
  writer.leave('}');
};
Trait.prototype.trace = function (writer) {
  if (this.metadata) {
    for (var key in this.metadata) {
      if (this.metadata.hasOwnProperty(key)) {
        this.metadata[key].trace(writer);
      }
    }
  }
  writer.writeLn(this);
};
function traceAbc(writer, abc) {
  abc.trace(writer);
}
function traceOperand(operand, abc, code) {
  var value = 0;
  switch (operand.size) {
  case 's08':
    value = code.readS8();
    break;
  case 'u08':
    value = code.readU8();
    break;
  case 's16':
    value = code.readS16();
    break;
  case 's24':
    value = code.readS24();
    break;
  case 'u30':
    value = code.readU30();
    break;
  case 'u32':
    value = code.readU32();
    break;
  default:
    true;
    break;
  }
  var description = '';
  switch (operand.type) {
  case '':
    break;
  case 'I':
    description = abc.constantPool.ints[value];
    break;
  case 'U':
    description = abc.constantPool.uints[value];
    break;
  case 'D':
    description = abc.constantPool.doubles[value];
    break;
  case 'S':
    description = abc.constantPool.strings[value];
    break;
  case 'N':
    description = abc.constantPool.namespaces[value];
    break;
  case 'CI':
    description = abc.classes[value];
    break;
  case 'M':
    return abc.constantPool.multinames[value];
  default:
    description = '?';
    break;
  }
  return operand.name + ':' + value + (description === '' ? '' : ' (' + description + ')');
}
function traceOperands(opcode, abc, code, rewind) {
  rewind = rewind || false;
  var old = code.position;
  var str = '';
  if (opcode.operands === null) {
    str = 'null';
  } else {
    opcode.operands.forEach(function (op, i) {
      str += traceOperand(op, abc, code);
      if (i < opcode.operands.length - 1) {
        str += ', ';
      }
    });
  }
  if (rewind) {
    code.seek(old);
  }
  return str;
}
MethodInfo.prototype.trace = function trace(writer) {
  var abc = this.abc;
  writer.enter('method' + (this.name ? ' ' + this.name : '') + ' {');
  writer.writeLn('flags: ' + getFlags(this.flags, 'NEED_ARGUMENTS|NEED_ACTIVATION|NEED_REST|HAS_OPTIONAL||NATIVE|SET_DXN|HAS_PARAM_NAMES'.split('|')));
  writer.writeLn('parameters: ' + this.parameters.map(function (x) {
    return (x.type ? Multiname.getQualifiedName(x.type) + '::' : '') + x.name;
  }));
  if (!this.code) {
    writer.leave('}');
    return;
  }
  var code = new AbcStream(this.code);
  traceArray(writer, 'traits', this.traits);
  writer.enter('code {');
  while (code.remaining() > 0) {
    var bc = code.readU8();
    var opcode = opcodeTable[bc];
    var str, defaultOffset, offset, count;
    str = ('' + code.position).padRight(' ', 6);
    switch (bc) {
    case OP_lookupswitch:
      str += opcode.name + ': defaultOffset: ' + code.readS24();
      var caseCount = code.readU30();
      str += ', caseCount: ' + caseCount;
      for (var i = 0; i < caseCount + 1; i++) {
        str += ' offset: ' + code.readS24();
      }
      writer.writeLn(str);
      break;
    default:
      if (opcode) {
        str += opcode.name.padRight(' ', 20);
        if (!opcode.operands) {
          true;
        } else {
          if (opcode.operands.length > 0) {
            str += traceOperands(opcode, abc, code);
          }
          writer.writeLn(str);
        }
      } else {
        true;
      }
      break;
    }
  }
  writer.leave('}');
  writer.leave('}');
};
var SourceTracer = function () {
    function literal(value) {
      if (value === undefined) {
        return 'undefined';
      } else if (value === null) {
        return 'null';
      } else if (typeof value === 'string') {
        return '"' + value + '"';
      } else {
        return String(value);
      }
    }
    function getSignature(mi, excludeTypesAndDefaultValues) {
      return mi.parameters.map(function (x) {
        var str = x.name;
        if (!excludeTypesAndDefaultValues) {
          if (x.type) {
            str += ':' + x.type.getName();
          }
          if (x.value !== undefined) {
            str += ' = ' + literal(x.value);
          }
        }
        return str;
      }).join(', ');
    }
    function SourceTracer(writer) {
      this.writer = writer;
    }
    SourceTracer.prototype = {
      traceTraits: function traceTraits(traits, isStatic, inInterfaceNamespace) {
        var writer = this.writer;
        var tracer = this;
        traits.forEach(function (trait) {
          var str;
          var accessModifier = Multiname.getAccessModifier(trait.name);
          var namespaceName = trait.name.namespaces[0].uri;
          if (namespaceName) {
            if (namespaceName === 'http://adobe.com/AS3/2006/builtin') {
              namespaceName = 'AS3';
            }
            if (accessModifier === 'public') {
              str = inInterfaceNamespace === namespaceName ? '' : namespaceName;
            } else {
              str = accessModifier;
            }
          } else {
            str = accessModifier;
          }
          if (isStatic) {
            str += ' static';
          }
          if (trait.isSlot() || trait.isConst()) {
            tracer.traceMetadata(trait.metadata);
            if (trait.isConst()) {
              str += ' const';
            } else {
              str += ' var';
            }
            str += ' ' + trait.name.getName();
            if (trait.typeName) {
              str += ':' + trait.typeName.getName();
            }
            if (trait.value) {
              str += ' = ' + literal(trait.value);
            }
            writer.writeLn(str + ';');
          } else if (trait.isMethod() || trait.isGetter() || trait.isSetter()) {
            tracer.traceMetadata(trait.metadata);
            var mi = trait.methodInfo;
            if (trait.attributes & ATTR_Override) {
              str += ' override';
            }
            if (mi.isNative()) {
              str += ' native';
            }
            str += ' function';
            str += trait.isGetter() ? ' get' : trait.isSetter() ? ' set' : '';
            str += ' ' + trait.name.getName();
            str += '(' + getSignature(mi) + ')';
            str += mi.returnType ? ':' + mi.returnType.getName() : '';
            if (true) {
              var className;
              var prefix = '';
              if (trait.holder instanceof ClassInfo) {
                className = trait.holder.instanceInfo.name;
                if (className.namespaces[0].uri) {
                  prefix += className.namespaces[0].uri + '::';
                }
                prefix += className.getName();
                prefix += '$/';
              } else if (trait.holder instanceof InstanceInfo) {
                className = trait.holder.name;
                if (className.namespaces[0].uri) {
                  prefix += className.namespaces[0].uri + '::';
                }
                prefix += className.getName();
                prefix += '/';
              } else {
                prefix = 'global/';
              }
              var getSet = trait.isGetter() ? 'get ' : trait.isSetter() ? 'set ' : '';
              if (!mi.isNative()) {
              }
            }
            if (mi.isNative()) {
              writer.writeLn(str + ';');
            } else {
              if (inInterfaceNamespace) {
                writer.writeLn(str + ';');
              } else {
                writer.writeLn(str + ' { notImplemented("' + trait.name.getName() + '"); }');
              }
            }
          } else if (trait.isClass()) {
            var className = trait.classInfo.instanceInfo.name;
            writer.enter('package ' + className.namespaces[0].uri + ' {\n');
            tracer.traceMetadata(trait.metadata);
            tracer.traceClass(trait.classInfo);
            writer.leave('\n}');
            tracer.traceClassStub(trait);
          } else {
            notImplemented();
          }
        });
      },
      traceClassStub2: function traceClassStub(trait) {
        var writer = this.writer;
        var ci = trait.classInfo;
        var ii = ci.instanceInfo;
        var name = ii.name.getName();
        var native = trait.metadata ? trait.metadata.native : null;
        if (!native) {
          return false;
        }
        writer.writeLn('Cut and paste the following into `native.js\' and edit accordingly');
        writer.writeLn('8< --------------------------------------------------------------');
        writer.enter('natives.' + native.cls + ' = function ' + native.cls + '(runtime, scope, instanceConstructor, baseClass) {');
        writer.writeLn('var c = new Class("' + name + '", instanceConstructor, ApplicationDomain.passthroughCallable(instanceConstructor));');
        writer.writeLn('c.extend(baseClass);\n');
        function traceTraits(traits, isStatic) {
          var nativeMethodTraits = [];
          traits.forEach(function (trait, i) {
            if (trait.isMethod() || trait.isGetter() || trait.isSetter()) {
              if (trait.methodInfo.isNative()) {
                nativeMethodTraits.push(trait);
              }
            }
          });
          nativeMethodTraits.forEach(function (trait, i) {
            var mi = trait.methodInfo;
            var traitName = trait.name.getName();
            writer.writeLn('// ' + traitName + ' :: ' + (mi.parameters.length ? getSignature(mi) : 'void') + ' -> ' + (mi.returnType ? mi.returnType.getName() : 'any'));
            var prop;
            if (trait.isGetter()) {
              prop = '"get ' + traitName + '"';
            } else if (trait.isSetter()) {
              prop = '"set ' + traitName + '"';
            } else {
              prop = traitName;
            }
            writer.enter(prop + ': function ' + traitName + '(' + getSignature(mi, true) + ') {');
            writer.writeLn('  notImplemented("' + name + '.' + traitName + '");');
            writer.leave('}' + (i === nativeMethodTraits.length - 1 ? '' : ',\n'));
          });
        }
        writer.enter('c.nativeStatics = {');
        traceTraits(ci.traits, true);
        writer.leave('};\n');
        writer.enter('c.nativeMethods = {');
        traceTraits(ii.traits);
        writer.leave('};\n');
        writer.writeLn('return c;');
        writer.leave('};');
        writer.writeLn('-------------------------------------------------------------- >8');
        return true;
      },
      traceClassStub: function traceClassStub(trait) {
        var writer = this.writer;
        var ci = trait.classInfo;
        var ii = ci.instanceInfo;
        var className = ii.name.getName();
        var native = trait.metadata ? trait.metadata.native : null;
        writer.writeLn('Cut and paste the following glue and edit accordingly.');
        writer.writeLn('Class ' + ii);
        writer.writeLn('8< --------------------------------------------------------------');
        var uri = ii.name.namespaces[0].uri;
        writer.enter('var ' + className + 'Definition = (function () {');
        function maxTraitNameLength(traits) {
          var length = 0;
          traits.forEach(function (t) {
            length = Math.max(t.name.name.length, length);
          });
          return length;
        }
        function quote(s) {
          return '\'' + s + '\'';
        }
        function filterTraits(traits, isNative) {
          function isMethod(x) {
            return x.isMethod() || x.isGetter() || x.isSetter();
          }
          return {
            properties: traits.filter(function (trait) {
              return !isNative && !isMethod(trait);
            }),
            methods: traits.filter(function (trait) {
              return isMethod(trait) && isNative === trait.methodInfo.isNative();
            })
          };
        }
        function writeTraits(traits, isNative, isStatic) {
          traits = filterTraits(traits, isNative);
          var methods = [];
          var gettersAndSetters = createEmptyObject();
          traits.methods.forEach(function (trait, i) {
            var traitName = trait.name.getName();
            if (trait.isGetter() || trait.isSetter()) {
              if (!gettersAndSetters[traitName]) {
                gettersAndSetters[traitName] = [];
              }
              gettersAndSetters[traitName].push(trait);
            } else {
              methods.push(trait);
            }
          });
          function writeTrait(trait, writeComma) {
            var mi = trait.methodInfo;
            var traitName = trait.name.getName();
            var signature = '// (' + (mi.parameters.length ? getSignature(mi) : 'void') + ') -> ' + (mi.returnType ? mi.returnType.getName() : 'any');
            var propertyName = traitName;
            if (trait.isGetter()) {
              propertyName = 'get';
            } else if (trait.isSetter()) {
              propertyName = 'set';
            }
            writer.enter(propertyName + ': function ' + traitName + '(' + getSignature(mi, true) + ') { ' + signature);
            writer.writeLn('notImplemented("' + className + '.' + traitName + '");');
            if (!isStatic) {
              if (trait.isGetter()) {
                writer.writeLn('return this._' + traitName + ';');
              } else if (trait.isSetter()) {
                writer.writeLn('this._' + traitName + ' = ' + mi.parameters[0].name + ';');
              }
            }
            writer.leave('}' + (writeComma ? ',' : ''));
          }
          for (var i = 0; i < methods.length; i++) {
            writeTrait(methods[i], i < methods.length - 1);
          }
          var keyValues = toKeyValueArray(gettersAndSetters);
          for (var j = 0; j < keyValues.length; j++) {
            writer.enter(keyValues[j][0] + ': {');
            var list = keyValues[j][1];
            for (var i = 0; i < list.length; i++) {
              writeTrait(list[i], i < list.length - 1);
            }
            writer.leave('}' + (j < keyValues.length - 1 ? ',' : ''));
          }
          traits.properties.forEach(function (trait, i) {
            var traitName = trait.name.getName();
            var last = i === traits.properties.length - 1;
            if (trait.name.getNamespace().isPublic()) {
              writer.writeLn(traitName + ': ' + quote('public ' + trait.name.name) + (last ? '' : ','));
            }
          });
        }
        writer.enter('return {');
        writer.writeLn('// (' + getSignature(ii.init, false) + ')');
        writer.writeLn('__class__: "' + uri + '.' + className + '",');
        writer.enter('initialize: function () {');
        writer.leave('},');
        writer.enter('__glue__: {');
        writer.enter('native: {');
        writer.enter('static: {');
        writeTraits(ci.traits, true, true);
        writer.leave('},');
        writer.enter('instance: {');
        writeTraits(ii.traits, true);
        writer.leave('}');
        writer.leave('},');
        writer.enter('script: {');
        writer.writeLn('instance: Glue.ALL');
        writer.leave('}');
        writer.leave('}');
        writer.leave('};');
        writer.leave('}).call(this);');
        writer.writeLn('-------------------------------------------------------------- >8');
        return true;
      },
      traceClass: function traceClass(ci) {
        var writer = this.writer;
        var ii = ci.instanceInfo;
        var name = ii.name;
        var str = Multiname.getAccessModifier(name);
        if (ii.isFinal()) {
          str += ' final';
        }
        if (!ii.isSealed()) {
          str += ' dynamic';
        }
        str += ii.isInterface() ? ' interface ' : ' class ';
        str += name.getName();
        if (ii.superName && ii.superName.getName() !== 'Object') {
          str += ' extends ' + ii.superName.getName();
        }
        if (ii.interfaces.length) {
          str += ' implements ' + ii.interfaces.map(function (x) {
            return x.getName();
          }).join(', ');
        }
        writer.enter(str + ' {');
        if (!ii.isInterface()) {
          writer.writeLn('public function ' + name.getName() + '(' + getSignature(ii.init) + ') {}');
        }
        var interfaceNamespace;
        if (ii.isInterface()) {
          interfaceNamespace = name.namespaces[0].uri + ':' + name.name;
        }
        this.traceTraits(ci.traits, true, interfaceNamespace);
        this.traceTraits(ii.traits, false, interfaceNamespace);
        writer.leave('}');
      },
      traceMetadata: function traceMetadata(metadata) {
        var writer = this.writer;
        for (var key in metadata) {
          if (metadata.hasOwnProperty(key)) {
            if (key.indexOf('__') === 0) {
              continue;
            }
            writer.writeLn('[' + key + '(' + metadata[key].value.map(function (m) {
              var str = m.key ? m.key + '=' : '';
              return str + '"' + m.value + '"';
            }).join(', ') + ')]');
          }
        }
      }
    };
    return SourceTracer;
  }();
function traceSource(writer, abc) {
  var tracer = new SourceTracer(writer);
  abc.scripts.forEach(function (script) {
    tracer.traceTraits(script.traits);
  });
}
function traceStatistics(writer, abc) {
  var libraryClassCounter = new Shumway.Metrics.Counter(true);
  var librarySuperClassCounter = new Shumway.Metrics.Counter(true);
  var libraryMethodCounter = new Shumway.Metrics.Counter(true);
  var libraryProperties = new Shumway.Metrics.Counter(true);
  var definedClasses = {};
  var definedMethods = {};
  var definedProperties = {};
  abc.classes.forEach(function (x) {
    var className = x.instanceInfo.name.name;
    definedClasses[className] = true;
  });
  abc.scripts.forEach(function (s) {
    s.traits.forEach(function (t) {
      if (t.isClass()) {
        var superClassName = t.classInfo.instanceInfo.superName ? t.classInfo.instanceInfo.superName.name : '?';
        if (!(superClassName in definedClasses)) {
          librarySuperClassCounter.count(superClassName);
        }
        t.classInfo.traits.forEach(function (st) {
          if (st.isMethod()) {
            definedMethods[st.name.name] = true;
          } else {
            definedProperties[st.name.name] = true;
          }
        });
        t.classInfo.instanceInfo.traits.forEach(function (it) {
          if (it.isMethod() && !(it.attributes & ATTR_Override)) {
            definedMethods[it.name.name] = true;
          } else {
            definedProperties[it.name.name] = true;
          }
        });
      }
    });
  });
  var opCounter = new Shumway.Metrics.Counter(true);
  abc.methods.forEach(function (m) {
    if (!m.code) {
      return;
    }
    function readOperand(operand) {
      var value = 0;
      switch (operand.size) {
      case 's08':
        value = code.readS8();
        break;
      case 'u08':
        value = code.readU8();
        break;
      case 's16':
        value = code.readS16();
        break;
      case 's24':
        value = code.readS24();
        break;
      case 'u30':
        value = code.readU30();
        break;
      case 'u32':
        value = code.readU32();
        break;
      default:
        true;
        break;
      }
      var description = '';
      switch (operand.type) {
      case '':
        break;
      case 'I':
        description = abc.constantPool.ints[value];
        break;
      case 'U':
        description = abc.constantPool.uints[value];
        break;
      case 'D':
        description = abc.constantPool.doubles[value];
        break;
      case 'S':
        description = abc.constantPool.strings[value];
        break;
      case 'N':
        description = abc.constantPool.namespaces[value];
        break;
      case 'CI':
        description = abc.classes[value];
        break;
      case 'M':
        description = abc.constantPool.multinames[value];
        break;
      default:
        description = '?';
        break;
      }
      return description;
    }
    var code = new AbcStream(m.code);
    while (code.remaining() > 0) {
      var bc = code.readU8();
      var op = opcodeTable[bc];
      var operands = null;
      if (op) {
        opCounter.count(op.name);
        if (op.operands) {
          operands = op.operands.map(readOperand);
        }
        switch (bc) {
        case OP_call:
        case OP_callmethod:
          continue;
        case OP_callproperty:
        case OP_callproplex:
        case OP_callpropvoid:
        case OP_callstatic:
        case OP_callsuper:
        case OP_callsupervoid:
          if (operands[0] && !(operands[0].name in definedMethods)) {
            libraryMethodCounter.count(operands[0].name);
          }
          break;
        case OP_constructprop:
          if (operands[0] && !(operands[0].name in definedClasses)) {
            libraryClassCounter.count(operands[0].name);
          }
          break;
        case OP_getproperty:
        case OP_setproperty:
          if (operands[0] && !(operands[0].name in definedProperties)) {
            libraryProperties.count(operands[0].name);
          }
          break;
        }
      }
    }
  });
  writer.writeLn(JSON.stringify({
    definedClasses: definedClasses,
    definedMethods: definedMethods,
    definedProperties: definedProperties,
    libraryClasses: libraryClassCounter.counts,
    librarySuperClasses: librarySuperClassCounter.counts,
    libraryMethods: libraryMethodCounter.counts,
    libraryProperties: libraryProperties.counts,
    operations: opCounter.counts
  }, null, 2));
}
var Shumway;
(function (Shumway) {
  (function (AVM2) {
    var OP = Shumway.AVM2.ABC.OP;
    var Scope = Shumway.AVM2.Runtime.Scope;
    var asCoerceByMultiname = Shumway.AVM2.Runtime.asCoerceByMultiname;
    var asGetSlot = Shumway.AVM2.Runtime.asGetSlot;
    var asSetSlot = Shumway.AVM2.Runtime.asSetSlot;
    var asHasNext2 = Shumway.AVM2.Runtime.asHasNext2;
    var asCoerce = Shumway.AVM2.Runtime.asCoerce;
    var asCoerceString = Shumway.AVM2.Runtime.asCoerceString;
    var asAsType = Shumway.AVM2.Runtime.asAsType;
    var asTypeOf = Shumway.AVM2.Runtime.asTypeOf;
    var asIsInstanceOf = Shumway.AVM2.Runtime.asIsInstanceOf;
    var asIsType = Shumway.AVM2.Runtime.asIsType;
    var applyType = Shumway.AVM2.Runtime.applyType;
    var createFunction = Shumway.AVM2.Runtime.createFunction;
    var createClass = Shumway.AVM2.Runtime.createClass;
    var getDescendants = Shumway.AVM2.Runtime.getDescendants;
    var checkFilter = Shumway.AVM2.Runtime.checkFilter;
    var asAdd = Shumway.AVM2.Runtime.asAdd;
    var translateError = Shumway.AVM2.Runtime.translateError;
    var asCreateActivation = Shumway.AVM2.Runtime.asCreateActivation;
    var sliceArguments = Shumway.AVM2.Runtime.sliceArguments;
    var boxValue = Shumway.ObjectUtilities.boxValue;
    var popManyInto = Shumway.ArrayUtilities.popManyInto;
    var construct = Shumway.AVM2.Runtime.construct;
    var Multiname = Shumway.AVM2.ABC.Multiname;
    var ScopeStack = function () {
        function ScopeStack(parent) {
          this.parent = parent;
          this.stack = [];
          this.isWith = [];
        }
        ScopeStack.prototype.push = function (object, isWith) {
          this.stack.push(object);
          this.isWith.push(!(!isWith));
        };
        ScopeStack.prototype.get = function (index) {
          return this.stack[index];
        };
        ScopeStack.prototype.clear = function () {
          this.stack.length = 0;
          this.isWith.length = 0;
        };
        ScopeStack.prototype.pop = function () {
          this.isWith.pop();
          this.stack.pop();
        };
        ScopeStack.prototype.topScope = function () {
          if (!this.scopes) {
            this.scopes = [];
          }
          var parent = this.parent;
          for (var i = 0; i < this.stack.length; i++) {
            var object = this.stack[i], isWith = this.isWith[i], scope = this.scopes[i];
            if (!scope || scope.parent !== parent || scope.object !== object || scope.isWith !== isWith) {
              scope = this.scopes[i] = new Scope(parent, object, isWith);
            }
            parent = scope;
          }
          return parent;
        };
        return ScopeStack;
      }();
    function popNameInto(stack, mn, out) {
      out.flags = mn.flags;
      if (mn.isRuntimeName()) {
        out.name = stack.pop();
      } else {
        out.name = mn.name;
      }
      if (mn.isRuntimeNamespace()) {
        out.namespaces = [
          stack.pop()
        ];
      } else {
        out.namespaces = mn.namespaces;
      }
    }
    var Interpreter = function () {
        function Interpreter() {
        }
        Interpreter.interpretMethod = function ($this, method, savedScope, methodArgs) {
          true;
          Counter.count('Interpret Method');
          var abc = method.abc;
          var ints = abc.constantPool.ints;
          var uints = abc.constantPool.uints;
          var doubles = abc.constantPool.doubles;
          var strings = abc.constantPool.strings;
          var methods = abc.methods;
          var multinames = abc.constantPool.multinames;
          var domain = abc.applicationDomain;
          var exceptions = method.exceptions;
          var locals = [
              $this
            ];
          var stack = [], scopeStack = new ScopeStack(savedScope);
          var parameterCount = method.parameters.length;
          var argCount = methodArgs.length;
          var value;
          for (var i = 0; i < parameterCount; i++) {
            var parameter = method.parameters[i];
            if (i < argCount) {
              value = methodArgs[i];
            } else {
              value = parameter.value;
            }
            if (parameter.type && !parameter.type.isAnyName()) {
              value = asCoerceByMultiname(domain, parameter.type, value);
            }
            locals.push(value);
          }
          if (method.needsRest()) {
            locals.push(sliceArguments(methodArgs, parameterCount));
          } else if (method.needsArguments()) {
            locals.push(sliceArguments(methodArgs, 0));
          }
          var bytecodes = method.analysis.bytecodes;
          var object, index, multiname, result, a, b, args = [], mn = Multiname.TEMPORARY;
          interpretLabel:
            for (var pc = 0, end = bytecodes.length; pc < end;) {
              try {
                var bc = bytecodes[pc];
                var op = bc.op;
                switch (op | 0) {
                case 3:
                  throw stack.pop();
                case 4:
                  popNameInto(stack, multinames[bc.index], mn);
                  stack.push(stack.pop().asGetSuper(savedScope, mn.namespaces, mn.name, mn.flags));
                  break;
                case 5:
                  value = stack.pop();
                  popNameInto(stack, multinames[bc.index], mn);
                  stack.pop().asSetSuper(savedScope, mn.namespaces, mn.name, mn.flags, value);
                  break;
                case 8:
                  locals[bc.index] = undefined;
                  break;
                case 12:
                  b = stack.pop();
                  a = stack.pop();
                  pc = !(a < b) ? bc.offset : pc + 1;
                  continue;
                case 24:
                  b = stack.pop();
                  a = stack.pop();
                  pc = a >= b ? bc.offset : pc + 1;
                  continue;
                case 13:
                  b = stack.pop();
                  a = stack.pop();
                  pc = !(a <= b) ? bc.offset : pc + 1;
                  continue;
                case 23:
                  b = stack.pop();
                  a = stack.pop();
                  pc = a > b ? bc.offset : pc + 1;
                  continue;
                case 14:
                  b = stack.pop();
                  a = stack.pop();
                  pc = !(a > b) ? bc.offset : pc + 1;
                  continue;
                case 22:
                  b = stack.pop();
                  a = stack.pop();
                  pc = a <= b ? bc.offset : pc + 1;
                  continue;
                case 15:
                  b = stack.pop();
                  a = stack.pop();
                  pc = !(a >= b) ? bc.offset : pc + 1;
                  continue;
                case 21:
                  b = stack.pop();
                  a = stack.pop();
                  pc = a < b ? bc.offset : pc + 1;
                  continue;
                case 16:
                  pc = bc.offset;
                  continue;
                case 17:
                  pc = !(!stack.pop()) ? bc.offset : pc + 1;
                  continue;
                case 18:
                  pc = !stack.pop() ? bc.offset : pc + 1;
                  continue;
                case 19:
                  b = stack.pop();
                  a = stack.pop();
                  pc = a == b ? bc.offset : pc + 1;
                  continue;
                case 20:
                  b = stack.pop();
                  a = stack.pop();
                  pc = a != b ? bc.offset : pc + 1;
                  continue;
                case 25:
                  b = stack.pop();
                  a = stack.pop();
                  pc = a === b ? bc.offset : pc + 1;
                  continue;
                case 26:
                  b = stack.pop();
                  a = stack.pop();
                  pc = a !== b ? bc.offset : pc + 1;
                  continue;
                case 27:
                  index = stack.pop();
                  if (index < 0 || index >= bc.offsets.length) {
                    index = bc.offsets.length - 1;
                  }
                  pc = bc.offsets[index];
                  continue;
                case 28:
                  scopeStack.push(boxValue(stack.pop()), true);
                  break;
                case 29:
                  scopeStack.pop();
                  break;
                case 30:
                  index = stack.pop();
                  stack[stack.length - 1] = boxValue(stack[stack.length - 1]).asNextName(index);
                  break;
                case 35:
                  index = stack.pop();
                  stack[stack.length - 1] = boxValue(stack[stack.length - 1]).asNextValue(index);
                  break;
                case 50:
                  result = asHasNext2(locals[bc.object], locals[bc.index]);
                  locals[bc.object] = result.object;
                  locals[bc.index] = result.index;
                  stack.push(!(!result.index));
                  break;
                case 32:
                  stack.push(null);
                  break;
                case 33:
                  stack.push(undefined);
                  break;
                case 36:
                case 37:
                  stack.push(bc.value);
                  break;
                case 44:
                  stack.push(strings[bc.index]);
                  break;
                case 45:
                  stack.push(ints[bc.index]);
                  break;
                case 46:
                  stack.push(uints[bc.index]);
                  break;
                case 47:
                  stack.push(doubles[bc.index]);
                  break;
                case 38:
                  stack.push(true);
                  break;
                case 39:
                  stack.push(false);
                  break;
                case 40:
                  stack.push(NaN);
                  break;
                case 41:
                  stack.pop();
                  break;
                case 42:
                  stack.push(stack[stack.length - 1]);
                  break;
                case 43:
                  object = stack[stack.length - 1];
                  stack[stack.length - 1] = stack[stack.length - 2];
                  stack[stack.length - 2] = object;
                  break;
                case 48:
                  scopeStack.push(boxValue(stack.pop()), false);
                  break;
                case 64:
                  stack.push(createFunction(methods[bc.index], scopeStack.topScope(), true));
                  break;
                case 65:
                  popManyInto(stack, bc.argCount, args);
                  object = stack.pop();
                  stack[stack.length - 1] = stack[stack.length - 1].apply(object, args);
                  break;
                case 66:
                  popManyInto(stack, bc.argCount, args);
                  stack[stack.length - 1] = construct(stack[stack.length - 1], args);
                  break;
                case 71:
                  return;
                case 72:
                  if (method.returnType) {
                    return asCoerceByMultiname(domain, method.returnType, stack.pop());
                  }
                  return stack.pop();
                case 73:
                  popManyInto(stack, bc.argCount, args);
                  object = stack.pop();
                  savedScope.object.baseClass.instanceConstructorNoInitialize.apply(object, args);
                  break;
                case 74:
                  popManyInto(stack, bc.argCount, args);
                  popNameInto(stack, multinames[bc.index], mn);
                  object = boxValue(stack[stack.length - 1]);
                  object = object.asConstructProperty(mn.namespaces, mn.name, mn.flags, args);
                  stack[stack.length - 1] = object;
                  break;
                case 75:
                  Shumway.Debug.notImplemented('OP.callsuperid');
                  break;
                case 76:
                case 70:
                case 79:
                  popManyInto(stack, bc.argCount, args);
                  popNameInto(stack, multinames[bc.index], mn);
                  result = boxValue(stack.pop()).asCallProperty(mn.namespaces, mn.name, mn.flags, op === 76, args);
                  if (op !== 79) {
                    stack.push(result);
                  }
                  break;
                case 69:
                case 78:
                  popManyInto(stack, bc.argCount, args);
                  popNameInto(stack, multinames[bc.index], mn);
                  result = stack.pop().asCallSuper(savedScope, mn.namespaces, mn.name, mn.flags, args);
                  if (op !== 78) {
                    stack.push(result);
                  }
                  break;
                case 83:
                  popManyInto(stack, bc.argCount, args);
                  stack[stack.length - 1] = applyType(domain, stack[stack.length - 1], args);
                  break;
                case 85:
                  object = {};
                  for (var i = 0; i < bc.argCount; i++) {
                    value = stack.pop();
                    object[Multiname.getPublicQualifiedName(stack.pop())] = value;
                  }
                  stack.push(object);
                  break;
                case 86:
                  object = [];
                  popManyInto(stack, bc.argCount, args);
                  object.push.apply(object, args);
                  stack.push(object);
                  break;
                case 87:
                  true;
                  stack.push(asCreateActivation(method));
                  break;
                case 88:
                  stack[stack.length - 1] = createClass(abc.classes[bc.index], stack[stack.length - 1], scopeStack.topScope());
                  break;
                case 89:
                  popNameInto(stack, multinames[bc.index], mn);
                  stack.push(getDescendants(stack.pop(), mn));
                  break;
                case 90:
                  true;
                  stack.push(exceptions[bc.index].scopeObject);
                  break;
                case 94:
                case 93:
                  popNameInto(stack, multinames[bc.index], mn);
                  stack.push(scopeStack.topScope().findScopeProperty(mn.namespaces, mn.name, mn.flags, domain, op === 93, false));
                  break;
                case 96:
                  multiname = multinames[bc.index];
                  object = scopeStack.topScope().findScopeProperty(multiname.namespaces, multiname.name, multiname.flags, domain, true, false);
                  stack.push(object.asGetProperty(multiname.namespaces, multiname.name, multiname.flags));
                  break;
                case 104:
                case 97:
                  value = stack.pop();
                  popNameInto(stack, multinames[bc.index], mn);
                  boxValue(stack.pop()).asSetProperty(mn.namespaces, mn.name, mn.flags, value);
                  break;
                case 98:
                  stack.push(locals[bc.index]);
                  break;
                case 99:
                  locals[bc.index] = stack.pop();
                  break;
                case 100:
                  stack.push(savedScope.global.object);
                  break;
                case 101:
                  stack.push(scopeStack.get(bc.index));
                  break;
                case 102:
                  popNameInto(stack, multinames[bc.index], mn);
                  stack[stack.length - 1] = boxValue(stack[stack.length - 1]).asGetProperty(mn.namespaces, mn.name, mn.flags);
                  break;
                case 106:
                  popNameInto(stack, multinames[bc.index], mn);
                  stack[stack.length - 1] = boxValue(stack[stack.length - 1]).asDeleteProperty(mn.namespaces, mn.name, mn.flags);
                  break;
                case 108:
                  stack[stack.length - 1] = asGetSlot(stack[stack.length - 1], bc.index);
                  break;
                case 109:
                  value = stack.pop();
                  object = stack.pop();
                  asSetSlot(object, bc.index, value);
                  break;
                case 112:
                  stack[stack.length - 1] = stack[stack.length - 1] + '';
                  break;
                case 131:
                case 115:
                  stack[stack.length - 1] |= 0;
                  break;
                case 136:
                case 116:
                  stack[stack.length - 1] >>>= 0;
                  break;
                case 132:
                case 117:
                  stack[stack.length - 1] = +stack[stack.length - 1];
                  break;
                case 129:
                case 118:
                  stack[stack.length - 1] = !(!stack[stack.length - 1]);
                  break;
                case 120:
                  stack[stack.length - 1] = checkFilter(stack[stack.length - 1]);
                  break;
                case 128:
                  stack[stack.length - 1] = asCoerce(domain.getType(multinames[bc.index]), stack[stack.length - 1]);
                  break;
                case 130:
                  break;
                case 133:
                  stack[stack.length - 1] = asCoerceString(stack[stack.length - 1]);
                  break;
                case 135:
                  stack[stack.length - 2] = asAsType(stack.pop(), stack[stack.length - 1]);
                  break;
                case 137:
                  object = stack[stack.length - 1];
                  stack[stack.length - 1] = object == undefined ? null : object;
                  break;
                case 144:
                  stack[stack.length - 1] = -stack[stack.length - 1];
                  break;
                case 145:
                  ++stack[stack.length - 1];
                  break;
                case 146:
                  ++locals[bc.index];
                  break;
                case 147:
                  --stack[stack.length - 1];
                  break;
                case 148:
                  --locals[bc.index];
                  break;
                case 149:
                  stack[stack.length - 1] = asTypeOf(stack[stack.length - 1]);
                  break;
                case 150:
                  stack[stack.length - 1] = !stack[stack.length - 1];
                  break;
                case 151:
                  stack[stack.length - 1] = ~stack[stack.length - 1];
                  break;
                case 160:
                  stack[stack.length - 2] = asAdd(stack[stack.length - 2], stack.pop());
                  break;
                case 161:
                  stack[stack.length - 2] -= stack.pop();
                  break;
                case 162:
                  stack[stack.length - 2] *= stack.pop();
                  break;
                case 163:
                  stack[stack.length - 2] /= stack.pop();
                  break;
                case 164:
                  stack[stack.length - 2] %= stack.pop();
                  break;
                case 165:
                  stack[stack.length - 2] <<= stack.pop();
                  break;
                case 166:
                  stack[stack.length - 2] >>= stack.pop();
                  break;
                case 167:
                  stack[stack.length - 2] >>>= stack.pop();
                  break;
                case 168:
                  stack[stack.length - 2] &= stack.pop();
                  break;
                case 169:
                  stack[stack.length - 2] |= stack.pop();
                  break;
                case 170:
                  stack[stack.length - 2] ^= stack.pop();
                  break;
                case 171:
                  stack[stack.length - 2] = stack[stack.length - 2] == stack.pop();
                  break;
                case 172:
                  stack[stack.length - 2] = stack[stack.length - 2] === stack.pop();
                  break;
                case 173:
                  stack[stack.length - 2] = stack[stack.length - 2] < stack.pop();
                  break;
                case 174:
                  stack[stack.length - 2] = stack[stack.length - 2] <= stack.pop();
                  break;
                case 175:
                  stack[stack.length - 2] = stack[stack.length - 2] > stack.pop();
                  break;
                case 176:
                  stack[stack.length - 2] = stack[stack.length - 2] >= stack.pop();
                  break;
                case 177:
                  stack[stack.length - 2] = asIsInstanceOf(stack.pop(), stack[stack.length - 1]);
                  break;
                case 178:
                  stack[stack.length - 1] = asIsType(domain.getType(multinames[bc.index]), stack[stack.length - 1]);
                  break;
                case 179:
                  stack[stack.length - 2] = asIsType(stack.pop(), stack[stack.length - 1]);
                  break;
                case 180:
                  stack[stack.length - 2] = boxValue(stack.pop()).asHasProperty(null, stack[stack.length - 1]);
                  break;
                case 192:
                  stack[stack.length - 1] = (stack[stack.length - 1] | 0) + 1;
                  break;
                case 193:
                  stack[stack.length - 1] = (stack[stack.length - 1] | 0) - 1;
                  break;
                case 194:
                  locals[bc.index] = (locals[bc.index] | 0) + 1;
                  break;
                case 195:
                  locals[bc.index] = (locals[bc.index] | 0) - 1;
                  break;
                case 196:
                  stack[stack.length - 1] = ~stack[stack.length - 1];
                  break;
                case 197:
                  stack[stack.length - 2] = stack[stack.length - 2] + stack.pop() | 0;
                  break;
                case 198:
                  stack[stack.length - 2] = stack[stack.length - 2] - stack.pop() | 0;
                  break;
                case 199:
                  stack[stack.length - 2] = stack[stack.length - 2] * stack.pop() | 0;
                  break;
                case 208:
                case 209:
                case 210:
                case 211:
                  stack.push(locals[op - 208]);
                  break;
                case 212:
                case 213:
                case 214:
                case 215:
                  locals[op - 212] = stack.pop();
                  break;
                case 239:
                case 240:
                case 241:
                  break;
                default:
                  Shumway.Debug.notImplemented(Shumway.AVM2.opcodeName(op));
                }
                pc++;
              } catch (e) {
                if (exceptions.length < 1) {
                  throw e;
                }
                e = translateError(domain, e);
                for (var i = 0, j = exceptions.length; i < j; i++) {
                  var handler = exceptions[i];
                  if (pc >= handler.start && pc <= handler.end && (!handler.typeName || domain.getType(handler.typeName).isInstance(e))) {
                    stack.length = 0;
                    stack.push(e);
                    scopeStack.clear();
                    pc = handler.offset;
                    continue interpretLabel;
                  }
                }
                throw e;
              }
            }
        };
        return Interpreter;
      }();
    AVM2.Interpreter = Interpreter;
  }(Shumway.AVM2 || (Shumway.AVM2 = {})));
  var AVM2 = Shumway.AVM2;
}(Shumway || (Shumway = {})));
Shumway.AVM2.Runtime.enableVerifier.value = true;
release = true;
var avm2Root = SHUMWAY_ROOT + 'avm2/';
var builtinPath = avm2Root + 'generated/builtin/builtin.abc';
var avm1Path = avm2Root + 'generated/avm1lib/avm1lib.abc';
var BinaryFileReader = function binaryFileReader() {
    function constructor(url, responseType) {
      this.url = url;
      this.responseType = responseType || 'arraybuffer';
    }
    constructor.prototype = {
      readAll: function (progress, complete) {
        var url = this.url;
        var xhr = new XMLHttpRequest();
        var async = true;
        xhr.open('GET', this.url, async);
        xhr.responseType = this.responseType;
        if (progress) {
          xhr.onprogress = function (event) {
            progress(xhr.response, event.loaded, event.total);
          };
        }
        xhr.onreadystatechange = function (event) {
          if (xhr.readyState === 4) {
            if (xhr.status !== 200 && xhr.status !== 0) {
              unexpected('Path: ' + url + ' not found.');
              complete(null, xhr.statusText);
              return;
            }
            complete(xhr.response);
          }
        };
        xhr.send(null);
      },
      readAsync: function (ondata, onerror, onopen, oncomplete, onhttpstatus) {
        var xhr = new XMLHttpRequest({
            mozSystem: true
          });
        var url = this.url;
        xhr.open(this.method || 'GET', url, true);
        var isNotProgressive;
        try {
          xhr.responseType = 'moz-chunked-arraybuffer';
          isNotProgressive = xhr.responseType !== 'moz-chunked-arraybuffer';
        } catch (e) {
          isNotProgressive = true;
        }
        if (isNotProgressive) {
          xhr.responseType = 'arraybuffer';
        }
        xhr.onprogress = function (e) {
          if (isNotProgressive)
            return;
          ondata(new Uint8Array(xhr.response), {
            loaded: e.loaded,
            total: e.total
          });
        };
        xhr.onreadystatechange = function (event) {
          if (xhr.readyState === 2 && onhttpstatus) {
            onhttpstatus(url, xhr.status, xhr.getAllResponseHeaders());
          }
          if (xhr.readyState === 4) {
            if (xhr.status !== 200 && xhr.status !== 0) {
              onerror(xhr.statusText);
            }
            if (isNotProgressive) {
              var buffer = xhr.response;
              ondata(new Uint8Array(buffer), {
                loaded: buffer.byteLength,
                total: buffer.byteLength
              });
            }
            if (oncomplete) {
              oncomplete();
            }
          } else if (xhr.readyState === 2 && onopen) {
            onopen();
          }
        };
        xhr.send(null);
      }
    };
    return constructor;
  }();
var libraryAbcs;
function grabAbc(abcName) {
  var entry = libraryScripts[abcName];
  if (entry) {
    var offset = entry.offset;
    var length = entry.length;
    return new AbcFile(new Uint8Array(libraryAbcs, offset, length), abcName);
  }
  return null;
}
var avm2;
function createAVM2(builtinPath, libraryPath, avm1Path, sysMode, appMode, next) {
  avm2 = new AVM2(sysMode, appMode, loadAVM1);
  var builtinAbc, avm1Abc;
  AVM2.loadPlayerglobal(libraryPath.abcs, libraryPath.catalog).then(function () {
    new BinaryFileReader(builtinPath).readAll(null, function (buffer) {
      builtinAbc = new AbcFile(new Uint8Array(buffer), 'builtin.abc');
      executeAbc();
    });
  });
  function loadAVM1(next) {
    new BinaryFileReader(avm1Path).readAll(null, function (buffer) {
      avm1Abc = new AbcFile(new Uint8Array(buffer), 'avm1.abc');
      ;
      avm2.systemDomain.executeAbc(avm1Abc);
      next();
    });
  }
  function executeAbc() {
    avm2.builtinsLoaded = false;
    avm2.systemDomain.onMessage.register('classCreated', Stubs.onClassCreated);
    avm2.systemDomain.executeAbc(builtinAbc);
    avm2.builtinsLoaded = true;
    console.info(JSON.stringify(Counter.toJSON()));
    console.timeEnd('Load AVM2');
    next(avm2);
  }
}
{
  var MAX_SNAP_DRAW_SCALE_TO_CACHE = 8;
  var CACHE_SNAP_DRAW_AFTER = 3;
  var BitmapDefinition = function () {
      function setBitmapData(value) {
        if (this._bitmapData) {
          this._bitmapData._changeNotificationTarget = null;
        }
        this._bitmapData = value;
        if (this._bitmapData) {
          this._bitmapData._changeNotificationTarget = this;
        }
        if (value) {
          var canvas = value._drawable;
          this._bbox = {
            xMin: 0,
            yMin: 0,
            xMax: canvas.width * 20,
            yMax: canvas.height * 20
          };
        } else {
          this._bbox = {
            xMin: 0,
            yMin: 0,
            xMax: 0,
            yMax: 0
          };
        }
        this._drawableChanged();
        this._invalidateBounds();
        this._invalidateTransform();
      }
      return {
        __class__: 'flash.display.Bitmap',
        draw: function (ctx, ratio, colorTransform) {
          if (!this._bitmapData) {
            return;
          }
          var scaledImage;
          ctx.save();
          if (this._pixelSnapping === 'auto' || this._pixelSnapping === 'always') {
            var transform = this._getConcatenatedTransform(null, true);
            var EPSILON = 0.001;
            var aInt = Math.abs(Math.round(transform.a));
            var dInt = Math.abs(Math.round(transform.d));
            var snapPixels;
            if (aInt >= 1 && aInt <= MAX_SNAP_DRAW_SCALE_TO_CACHE && dInt >= 1 && dInt <= MAX_SNAP_DRAW_SCALE_TO_CACHE && Math.abs(Math.abs(transform.a) / aInt - 1) <= EPSILON && Math.abs(Math.abs(transform.d) / dInt - 1) <= EPSILON && Math.abs(transform.b) <= EPSILON && Math.abs(transform.c) <= EPSILON) {
              if (aInt === 1 && dInt === 1) {
                snapPixels = true;
              } else {
                var sizeKey = aInt + 'x' + dInt;
                if (this._snapImageCache.size !== sizeKey) {
                  this._snapImageCache.size = sizeKey;
                  this._snapImageCache.hits = 0;
                  this._snapImageCache.image = null;
                }
                if (++this._snapImageCache.hits === CACHE_SNAP_DRAW_AFTER) {
                  this._cacheSnapImage(sizeKey, aInt, dInt);
                }
                scaledImage = this._snapImageCache.image;
                snapPixels = !(!scaledImage);
              }
            } else {
              snapPixels = false;
            }
            if (snapPixels) {
              ctx.setTransform(transform.a < 0 ? -1 : 1, 0, 0, transform.d < 0 ? -1 : 1, transform.tx / 20 | 0, transform.ty / 20 | 0);
            }
          }
          colorTransform.setAlpha(ctx, true);
          ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = this._smoothing;
          ctx.drawImage(scaledImage || this._bitmapData._getDrawable(), 0, 0);
          ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = false;
          ctx.restore();
          traceRenderer.value && frameWriter.writeLn('Bitmap.draw() snapping: ' + this._pixelSnapping + ', dimensions: ' + this._bitmapData._drawable.width + ' x ' + this._bitmapData._drawable.height);
        },
        _drawableChanged: function () {
          this._invalidate();
          this._snapImageCache.image = null;
          this._snapImageCache.hints = 0;
        },
        _cacheSnapImage: function (sizeKey, xScale, yScale) {
          Counter.count('Cache scaled image');
          var original = this._bitmapData._getDrawable();
          var canvas = document.createElement('canvas');
          canvas.width = xScale * original.width;
          canvas.height = yScale * original.height;
          var ctx = canvas.getContext('2d');
          ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = this._smoothing;
          ctx.drawImage(original, 0, 0, original.width, original.height, 0, 0, canvas.width, canvas.height);
          var cache = this._snapImageCache;
          var image = document.createElement('img');
          cache._tmp = [
            canvas,
            image
          ];
          if ('toBlob' in canvas) {
            canvas.toBlob(function (blob) {
              if (cache.size !== sizeKey) {
                return;
              }
              image.onload = function () {
                URL.revokeObjectURL(blob);
                if (cache.size === sizeKey) {
                  cache.image = image;
                }
              };
              image.src = URL.createObjectURL(blob);
            });
          } else {
            image.onload = function () {
              if (cache.size === sizeKey) {
                cache.image = image;
              }
            };
            image.src = canvas.toDataURL();
          }
        },
        initialize: function () {
        },
        __glue__: {
          native: {
            static: {},
            instance: {
              ctor: function (bitmapData, pixelSnapping, smoothing) {
                if (pixelSnapping === 'never' || pixelSnapping === 'always') {
                  this._pixelSnapping = pixelSnapping;
                } else {
                  this._pixelSnapping = 'auto';
                }
                this._smoothing = !(!smoothing);
                this._snapImageCache = {
                  hits: 0,
                  size: '',
                  image: null
                };
                if (!bitmapData && this.symbol) {
                  var symbol = this.symbol;
                  bitmapData = new flash.display.BitmapData(symbol.width, symbol.height, true, 0);
                  bitmapData._ctx.imageSmoothingEnabled = this._smoothing;
                  bitmapData._ctx.mozImageSmoothingEnabled = this._smoothing;
                  bitmapData._ctx.drawImage(symbol.img, 0, 0);
                  bitmapData._ctx.imageSmoothingEnabled = false;
                  bitmapData._ctx.mozImageSmoothingEnabled = false;
                }
                setBitmapData.call(this, bitmapData || null);
              },
              pixelSnapping: {
                get: function pixelSnapping() {
                  return this._pixelSnapping;
                },
                set: function pixelSnapping(value) {
                  this._pixelSnapping = value;
                }
              },
              smoothing: {
                get: function smoothing() {
                  return this._smoothing;
                },
                set: function smoothing(value) {
                  this._smoothing = value;
                }
              },
              bitmapData: {
                get: function bitmapData() {
                  return this._bitmapData;
                },
                set: setBitmapData
              }
            }
          }
        }
      };
    }.call(this);
}
var CACHE_DRAWABLE_AFTER = 10;
var BitmapDataDefinition = function () {
    function replaceRect(ctx, x, y, w, h, alpha) {
      if (alpha < 255) {
        ctx.clearRect(x, y, w, h);
      }
      if (alpha > 0) {
        ctx.fillRect(x, y, w, h);
      }
    }
    var def = {
        __class__: 'flash.display.BitmapData',
        initialize: function () {
          this._changeNotificationTarget = null;
          this._locked = false;
          this._requested = 0;
          this._cache = null;
          if (this.symbol) {
            this._img = this.symbol.img;
            this._skipCopyToCanvas = this.symbol.skipCopyToCanvas;
          }
        },
        _checkCanvas: function () {
          if (this._drawable === null)
            throw ArgumentError();
        },
        ctor: function (width, height, transparent, backgroundColor) {
          if (this._img) {
            width = this._img.naturalWidth || this._img.width;
            height = this._img.naturalHeight || this._img.height;
          } else if (isNaN(width + height) || width <= 0 || height <= 0) {
            throwError('ArgumentError', Errors.ArgumentError);
          }
          this._transparent = transparent === undefined ? true : !(!transparent);
          this._backgroundColor = backgroundColor === undefined ? 4294967295 : backgroundColor;
          if (!this._transparent) {
            this._backgroundColor |= 4278190080;
          }
          if (this._skipCopyToCanvas) {
            this._drawable = this._img;
          } else {
            var canvas = document.createElement('canvas');
            this._ctx = canvas.getContext('2d');
            canvas.width = width | 0;
            canvas.height = height | 0;
            this._drawable = canvas;
            if (!this._transparent || !this._img && this._backgroundColor) {
              this.fillRect(new flash.geom.Rectangle(0, 0, width | 0, height | 0), this._backgroundColor);
            }
            if (this._img) {
              this._ctx.drawImage(this._img, 0, 0);
            }
          }
        },
        dispose: function () {
          this._ctx = null;
          this._drawable.width = 0;
          this._drawable.height = 0;
          this._drawable = null;
        },
        draw: function (source, matrix, colorTransform, blendMode, clipRect, smoothing) {
          this._checkCanvas();
          var ctx = this._ctx;
          ctx.save();
          ctx.beginPath();
          if (clipRect && clipRect.width > 0 && clipRect.height > 0) {
            ctx.rect(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
            ctx.clip();
          }
          if (matrix) {
            ctx.transform(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty);
          }
          ctx.globalCompositeOperation = getBlendModeName(blendMode);
          ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = !(!smoothing);
          if (flash.display.BitmapData.class.isInstanceOf(source)) {
            ctx.drawImage(source._drawable, 0, 0);
          } else {
            new RenderVisitor(source, ctx, null, true).startFragment(matrix);
          }
          ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = false;
          ctx.restore();
          this._invalidate();
        },
        fillRect: function (rect, color) {
          this._checkCanvas();
          if (!this._transparent) {
            color |= 4278190080;
          }
          var ctx = this._ctx;
          ctx.fillStyle = argbUintToStr(color);
          replaceRect(ctx, rect.x, rect.y, rect.width, rect.height, color >>> 24 & 255);
          this._invalidate();
        },
        getPixel: function (x, y) {
          this._checkCanvas();
          var data = this._ctx.getImageData(x, y, 1, 1).data;
          return dataToRGB(data);
        },
        getPixel32: function (x, y) {
          this._checkCanvas();
          var data = this._ctx.getImageData(x, y, 1, 1).data;
          return dataToARGB(data);
        },
        _invalidate: function (changeRect) {
          if (changeRect) {
            somewhatImplemented('BitmapData._invalidate(changeRect)');
          }
          if (this._locked) {
            return;
          }
          if (this._changeNotificationTarget) {
            this._changeNotificationTarget._drawableChanged();
          }
          this._requested = 0;
          this._cache = null;
        },
        _getDrawable: function () {
          if (this._img === this._drawable) {
            return this._drawable;
          }
          this._requested++;
          if (this._requested >= CACHE_DRAWABLE_AFTER) {
            if (!this._cache) {
              Counter.count('Cache drawable');
              var img = document.createElement('img');
              if ('toBlob' in this._drawable) {
                this._drawable.toBlob(function (blob) {
                  img.src = URL.createObjectURL(blob);
                  img.onload = function () {
                    URL.revokeObjectURL(blob);
                  };
                });
              } else {
                img.src = this._drawable.toDataURL();
              }
              this._cache = img;
            }
            if (this._cache.width > 0) {
              return this._cache;
            }
          }
          return this._drawable;
        },
        setPixel: function (x, y, color) {
          this.fillRect({
            x: x,
            y: y,
            width: 1,
            height: 1
          }, color | 4278190080);
          this._invalidate();
        },
        setPixel32: function (x, y, color) {
          this.fillRect({
            x: x,
            y: y,
            width: 1,
            height: 1
          }, color);
          this._invalidate();
        },
        copyPixels: function copyPixels(sourceBitmapData, sourceRect, destPoint, alphaBitmapData, alphaPoint, mergeAlpha) {
          if (alphaBitmapData) {
            notImplemented('BitmapData.copyPixels w/ alpha');
          }
          var w = sourceRect.width;
          var h = sourceRect.height;
          var sx = sourceRect.x;
          var sy = sourceRect.y;
          var dx = destPoint.x;
          var dy = destPoint.y;
          var offsetx = -Math.min(0, sx, dx);
          var offsety = -Math.min(0, sy, dy);
          var correctionw = Math.min(0, this._ctx.canvas.width - dx - w, sourceBitmapData._drawable.width - sx - w) - offsetx;
          var correctionh = Math.min(0, this._ctx.canvas.height - dy - h, sourceBitmapData._drawable.height - sy - h) - offsety;
          if (!mergeAlpha) {
            this._ctx.clearRect(dx, dy, w, h);
          }
          if (w + correctionw > 0 && h + correctionh > 0) {
            this._ctx.drawImage(sourceBitmapData._drawable, sx + offsetx, sy + offsety, w + correctionw, h + correctionh, dx + offsetx, dy + offsety, w + correctionw, h + correctionh);
          }
          this._invalidate();
        },
        lock: function lock() {
          this._locked = true;
        },
        unlock: function unlock(changeRect) {
          this._locked = false;
          this._invalidate(changeRect);
        },
        clone: function () {
          this._checkCanvas();
          var bd = new flash.display.BitmapData(this._drawable.width, this._drawable.height, true, 0);
          bd._ctx.drawImage(this._drawable, 0, 0);
          return bd;
        },
        scroll: function (x, y) {
          this._checkCanvas();
          this._ctx.draw(this._drawable, x, y);
          this._ctx.save();
          var color = this._img ? 0 : this._backgroundColor;
          if (!this._transparent) {
            color |= 4278190080;
          }
          var alpha = color >>> 24 & 255;
          this._ctx.fillStyle = argbUintToStr(color);
          var w = this._drawable.width;
          var h = this._drawable.height;
          if (x > 0) {
            replaceRect(this._ctx, 0, 0, x, h, alpha);
          } else if (x < 0) {
            replaceRect(this._ctx, w + x, 0, -x, h, alpha);
          }
          if (y > 0) {
            replaceRect(this._ctx, 0, 0, w, y, alpha);
          } else if (y < 0) {
            replaceRect(this._ctx, h + y, w, -y, alpha);
          }
          this._ctx.restore();
          this._invalidate();
        },
        get width() {
          return this._drawable.width;
        },
        get height() {
          return this._drawable.height;
        }
      };
    var desc = Object.getOwnPropertyDescriptor;
    def.__glue__ = {
      native: {
        instance: {
          ctor: def.ctor,
          fillRect: def.fillRect,
          dispose: def.dispose,
          getPixel: def.getPixel,
          getPixel32: def.getPixel32,
          setPixel: def.setPixel,
          setPixel32: def.setPixel32,
          copyPixels: def.copyPixels,
          lock: def.lock,
          unlock: def.unlock,
          draw: def.draw,
          clone: def.clone,
          scroll: def.scroll,
          width: desc(def, 'width'),
          height: desc(def, 'height')
        }
      }
    };
    return def;
  }.call(this);
function dataToRGB(data) {
  return data[0] << 16 | data[1] << 8 | data[2];
}
function dataToARGB(data) {
  return data[3] << 24 | dataToRGB(data);
}
var DisplayObjectDefinition = function () {
    var blendModes;
    var nextInstanceId = 1;
    function generateName() {
      return 'instance' + nextInstanceId++;
    }
    var broadcastedEvents = {
        advanceFrame: false,
        enterFrame: true,
        constructChildren: false,
        frameConstructed: true,
        executeFrame: false,
        exitFrame: true,
        render: true
      };
    var point = {
        x: 0,
        y: 0
      };
    var def = {
        __class__: 'flash.display.DisplayObject',
        initialize: function () {
          var blendModeClass = flash.display.BlendMode.class;
          this._alpha = 1;
          this._animated = false;
          this._bbox = null;
          this._bitmap = null;
          this._blendMode = blendModeClass.NORMAL;
          this._bounds = {
            xMin: 0,
            xMax: 0,
            yMin: 0,
            yMax: 0,
            invalid: true
          };
          this._cacheAsBitmap = false;
          this._children = [];
          this._clipDepth = null;
          this._currentTransform = {
            a: 1,
            b: 0,
            c: 0,
            d: 1,
            tx: 0,
            ty: 0
          };
          this._concatenatedTransform = {
            a: 1,
            b: 0,
            c: 0,
            d: 1,
            tx: 0,
            ty: 0,
            invalid: true
          };
          this._current3DTransform = null;
          this._cxform = null;
          this._graphics = null;
          this._filters = [];
          this._loader = null;
          this._mouseChildren = true;
          this._mouseOver = false;
          this._mouseX = 0;
          this._mouseY = 0;
          this._name = null;
          this._opaqueBackground = null;
          this._owned = false;
          this._parent = null;
          this._rotation = 0;
          this._rotationCos = 1;
          this._rotationSin = 0;
          this._scale9Grid = null;
          this._scaleX = 1;
          this._scaleY = 1;
          this._stage = null;
          this._visible = true;
          this._hidden = false;
          this._wasCachedAsBitmap = false;
          this._destroyed = false;
          this._maskedObject = null;
          this._scrollRect = null;
          this._invalid = false;
          this._region = null;
          this._level = -1;
          this._index = -1;
          this._depth = -1;
          this._isContainer = false;
          this._invisible = false;
          this._zindex = 0;
          blendModes = [
            blendModeClass.NORMAL,
            blendModeClass.NORMAL,
            blendModeClass.LAYER,
            blendModeClass.MULTIPLY,
            blendModeClass.SCREEN,
            blendModeClass.LIGHTEN,
            blendModeClass.DARKEN,
            blendModeClass.DIFFERENCE,
            blendModeClass.ADD,
            blendModeClass.SUBTRACT,
            blendModeClass.INVERT,
            blendModeClass.ALPHA,
            blendModeClass.ERASE,
            blendModeClass.OVERLAY,
            blendModeClass.HARDLIGHT,
            blendModeClass.SHADER
          ];
          var s = this.symbol;
          if (s) {
            this._animated = s.animated || false;
            this._bbox = s.bbox || null;
            this._blendMode = this._resolveBlendMode(s.blendMode);
            this._children = s.children || [];
            this._clipDepth = s.clipDepth || null;
            this._cxform = s.cxform || null;
            this._loader = s.loader || null;
            this._name = s.name || null;
            this._owned = s.owned || false;
            this._parent = s.parent || null;
            this._level = isNaN(s.level) ? -1 : s.level;
            this._index = isNaN(s.index) ? -1 : s.index;
            this._depth = isNaN(s.depth) ? -1 : s.depth;
            this._root = s.root || null;
            this._stage = s.stage || null;
            var scale9Grid = s.scale9Grid;
            if (scale9Grid) {
              this._scale9Grid = new flash.geom.Rectangle(scale9Grid.left, scale9Grid.top, scale9Grid.right - scale9Grid.left, scale9Grid.bottom - scale9Grid.top);
            }
            var matrix = s.currentTransform;
            if (matrix) {
              this._setTransformMatrix(matrix, false);
            }
          }
          this._accessibilityProperties = null;
          var self = this;
          this._onBroadcastMessage = function (type) {
            var listeners = self._listeners;
            if (listeners[type]) {
              self._dispatchEvent(type);
            }
          };
        },
        _addEventListener: function addEventListener(type, listener, useCapture, priority) {
          if (broadcastedEvents[type] === false) {
            avm2.systemDomain.onMessage.register(type, listener);
            return;
          }
          if (type in broadcastedEvents && !this._listeners[type]) {
            avm2.systemDomain.onMessage.register(type, this._onBroadcastMessage);
          }
          this._addEventListenerImpl(type, listener, useCapture, priority);
        },
        _removeEventListener: function addEventListener(type, listener, useCapture) {
          if (broadcastedEvents[type] === false) {
            avm2.systemDomain.onMessage.unregister(type, listener);
            return;
          }
          this._removeEventListenerImpl(type, listener, useCapture);
          if (type in broadcastedEvents && !this._listeners[type]) {
            avm2.systemDomain.onMessage.unregister(type, this._onBroadcastMessage);
          }
        },
        _resolveBlendMode: function (blendModeNumeric) {
          return blendModes[blendModeNumeric] || flash.display.BlendMode.class.NORMAL;
        },
        _getConcatenatedTransform: function (targetCoordSpace, toDeviceSpace) {
          var stage = this._stage;
          if (this === this._stage) {
            return toDeviceSpace ? this._concatenatedTransform : this._currentTransform;
          }
          if (targetCoordSpace === this._parent) {
            return this._currentTransform;
          }
          var invalidNode = null;
          var m, m2, targetCoordMatrix;
          var currentNode = this;
          while (currentNode !== stage) {
            if (currentNode._concatenatedTransform.invalid) {
              invalidNode = currentNode;
            }
            if (currentNode === targetCoordSpace) {
              targetCoordMatrix = currentNode._concatenatedTransform;
            }
            currentNode = currentNode._parent;
          }
          if (invalidNode) {
            if (this._parent === stage) {
              m = this._concatenatedTransform;
              m2 = this._currentTransform;
              m.a = m2.a;
              m.b = m2.b;
              m.c = m2.c;
              m.d = m2.d;
              m.tx = m2.tx;
              m.ty = m2.ty;
            } else {
              var stack = [];
              var currentNode = this;
              while (currentNode !== invalidNode) {
                stack.push(currentNode);
                currentNode = currentNode._parent;
              }
              var node = invalidNode;
              do {
                var parent = node._parent;
                m = node._concatenatedTransform;
                m2 = node._currentTransform;
                if (parent) {
                  if (parent !== stage) {
                    var m3 = parent._concatenatedTransform;
                    m.a = m2.a * m3.a + m2.b * m3.c;
                    m.b = m2.a * m3.b + m2.b * m3.d;
                    m.c = m2.c * m3.a + m2.d * m3.c;
                    m.d = m2.d * m3.d + m2.c * m3.b;
                    m.tx = m2.tx * m3.a + m3.tx + m2.ty * m3.c;
                    m.ty = m2.ty * m3.d + m3.ty + m2.tx * m3.b;
                  }
                } else {
                  m.a = m2.a;
                  m.b = m2.b;
                  m.c = m2.c;
                  m.d = m2.d;
                  m.tx = m2.tx;
                  m.ty = m2.ty;
                }
                m.invalid = false;
                var nextNode = stack.pop();
                var children = node._children;
                for (var i = 0; i < children.length; i++) {
                  var child = children[i];
                  if (child !== nextNode) {
                    child._concatenatedTransform.invalid = true;
                  }
                }
                node = nextNode;
              } while (node);
            }
          } else {
            m = this._concatenatedTransform;
          }
          if (targetCoordSpace && targetCoordSpace !== this._stage) {
            m2 = targetCoordMatrix || targetCoordSpace._getConcatenatedTransform(null, false);
            var a = 1, b = 0, c = 0, d = 1, tx = 0, ty = 0;
            if (m2.b || m2.c) {
              var det = 1 / (m2.a * m2.d - m2.b * m2.c);
              a = m2.d * det;
              b = -m2.b * det;
              c = -m2.c * det;
              d = m2.a * det;
              tx = -(a * m2.tx + c * m2.ty);
              ty = -(b * m2.tx + d * m2.ty);
            } else {
              a = 1 / m2.a;
              d = 1 / m2.d;
              tx = m2.tx * -a;
              ty = m2.ty * -d;
            }
            return {
              a: a * m.a + c * m.b,
              b: b * m.a + d * m.b,
              c: a * m.c + c * m.d,
              d: b * m.c + d * m.d,
              tx: a * m.tx + c * m.ty + tx,
              ty: b * m.tx + d * m.ty + ty
            };
          }
          if (toDeviceSpace && stage) {
            m2 = stage._concatenatedTransform;
            return {
              a: m.a * m2.a,
              b: m.b * m2.d,
              c: m.c * m2.a,
              d: m.d * m2.d,
              tx: m.tx * m2.a + m2.tx,
              ty: m.ty * m2.d + m2.ty
            };
          }
          return m;
        },
        _applyCurrentTransform: function (pt) {
          var m = this._getConcatenatedTransform(null, false);
          var x = pt.x;
          var y = pt.y;
          pt.x = m.a * x + m.c * y + m.tx | 0;
          pt.y = m.d * y + m.b * x + m.ty | 0;
        },
        _applyConcatenatedInverseTransform: function (pt) {
          var m = this._getConcatenatedTransform(null, false);
          var det = 1 / (m.a * m.d - m.b * m.c);
          var x = pt.x - m.tx;
          var y = pt.y - m.ty;
          pt.x = (m.d * x - m.c * y) * det | 0;
          pt.y = (m.a * y - m.b * x) * det | 0;
        },
        _hitTest: function (use_xy, x, y, useShape, hitTestObject) {
          if (use_xy) {
            point.x = x;
            point.y = y;
            this._applyConcatenatedInverseTransform(point);
            var b = this._getContentBounds();
            if (!(point.x >= b.xMin && point.x < b.xMax && point.y >= b.yMin && point.y < b.yMax)) {
              return false;
            }
            if (!useShape || !this._graphics) {
              return true;
            }
            if (this._graphics) {
              var subpaths = this._graphics._paths;
              for (var i = 0, n = subpaths.length; i < n; i++) {
                var path = subpaths[i];
                if (path.isPointInPath(point.x, point.y)) {
                  return true;
                }
                if (path.strokeStyle) {
                  var strokePath = path._strokePath;
                  if (!strokePath) {
                    strokePath = path.strokePath(path.drawingStyles);
                    path._strokePath = strokePath;
                  }
                  if (strokePath.isPointInPath(point.x, point.y)) {
                    return true;
                  }
                }
              }
            }
            var children = this._children;
            for (var i = 0, n = children.length; i < n; i++) {
              var child = children[i];
              if (child._hitTest && child._hitTest(true, x, y, true, null)) {
                return true;
              }
            }
            return false;
          }
          var b1 = this.getBounds(this._stage);
          var b2 = hitTestObject.getBounds(hitTestObject._stage);
          x = Math.max(b1.xMin, b2.xMin);
          y = Math.max(b1.yMin, b2.yMin);
          var width = Math.min(b1.xMax, b2.xMax) - x;
          var height = Math.min(b1.yMax, b2.yMax) - y;
          return width > 0 && height > 0;
        },
        _invalidate: function () {
          this._invalid = true;
        },
        _invalidateBounds: function () {
          var currentNode = this;
          while (currentNode && !currentNode._bounds.invalid) {
            currentNode._bounds.invalid = true;
            currentNode = currentNode._parent;
          }
        },
        _invalidateTransform: function () {
          this._concatenatedTransform.invalid = true;
          if (this._parent) {
            this._parent._invalidateBounds();
          }
        },
        _setTransformMatrix: function (matrix, convertToTwips) {
          var a = matrix.a;
          var b = matrix.b;
          var c = matrix.c;
          var d = matrix.d;
          var tx, ty;
          if (convertToTwips) {
            tx = matrix.tx * 20 | 0;
            ty = matrix.ty * 20 | 0;
          } else {
            tx = matrix.tx;
            ty = matrix.ty;
          }
          var angle = a !== 0 ? Math.atan(b / a) : b > 0 ? Math.PI / 2 : -Math.PI / 2;
          this._rotation = angle * 180 / Math.PI;
          this._rotationCos = Math.cos(angle);
          this._rotationSin = Math.sin(angle);
          var sx = Math.sqrt(a * a + b * b);
          this._scaleX = a > 0 ? sx : -sx;
          var sy = Math.sqrt(d * d + c * c);
          this._scaleY = d > 0 ? sy : -sy;
          var transform = this._currentTransform;
          transform.a = a;
          transform.b = b;
          transform.c = c;
          transform.d = d;
          transform.tx = tx;
          transform.ty = ty;
          this._invalidateTransform();
        },
        get accessibilityProperties() {
          return this._accessibilityProperties;
        },
        set accessibilityProperties(val) {
          this._accessibilityProperties = val;
        },
        get alpha() {
          return this._alpha;
        },
        set alpha(val) {
          if (val === this._alpha) {
            return;
          }
          this._invalidate();
          this._alpha = val;
          this._animated = false;
        },
        get blendMode() {
          return this._blendMode;
        },
        set blendMode(val) {
          if (blendModes.indexOf(val) >= 0) {
            this._blendMode = val;
          } else {
            throwError('ArgumentError', Errors.InvalidEnumError, 'blendMode');
          }
          this._animated = false;
        },
        get cacheAsBitmap() {
          return this._cacheAsBitmap;
        },
        set cacheAsBitmap(val) {
          this._cacheAsBitmap = this._filters.length ? true : val;
          this._animated = false;
        },
        get filters() {
          return this._filters;
        },
        set filters(val) {
          if (val.length) {
            if (!this._filters.length)
              this._wasCachedAsBitmap = this._cacheAsBitmap;
            this._cacheAsBitmap = true;
          } else {
            this._cacheAsBitmap = this._wasCachedAsBitmap;
          }
          this._filters = val;
          this._animated = false;
        },
        get height() {
          var bounds = this._getContentBounds();
          var t = this._currentTransform;
          return Math.abs(t.b) * (bounds.xMax - bounds.xMin) + Math.abs(t.d) * (bounds.yMax - bounds.yMin) | 0;
        },
        set height(val) {
          if (val < 0) {
            return;
          }
          var u = Math.abs(this._rotationCos);
          var v = Math.abs(this._rotationSin);
          var bounds = this._getContentBounds();
          var baseHeight = v * (bounds.xMax - bounds.xMin) + u * (bounds.yMax - bounds.yMin);
          if (!baseHeight) {
            return;
          }
          var baseWidth = u * (bounds.xMax - bounds.xMin) + v * (bounds.yMax - bounds.yMin);
          this.scaleX = this.width / baseWidth;
          this.scaleY = val / baseHeight;
        },
        get loaderInfo() {
          return this._loader && this._loader._contentLoaderInfo || this._parent.loaderInfo;
        },
        get mask() {
          return this._mask;
        },
        set mask(val) {
          if (this._mask === val) {
            return;
          }
          this._invalidate();
          if (val && val._maskedObject) {
            val._maskedObject.mask = null;
          }
          this._mask = val;
          if (val) {
            val._maskedObject = this;
          }
          this._animated = false;
        },
        get name() {
          return this._name || (this._name = generateName());
        },
        set name(val) {
          this._name = val;
        },
        get mouseX() {
          if (!this._stage) {
            return 0;
          }
          point.x = this._stage._mouseX;
          point.y = this._stage._mouseY;
          this._applyConcatenatedInverseTransform(point);
          return point.x;
        },
        get mouseY() {
          if (!this._stage) {
            return 0;
          }
          point.x = this._stage._mouseX;
          point.y = this._stage._mouseY;
          this._applyConcatenatedInverseTransform(point);
          return point.y;
        },
        get opaqueBackground() {
          return this._opaqueBackground;
        },
        set opaqueBackground(val) {
          this._opaqueBackground = val;
          this._animated = false;
        },
        get parent() {
          return this._index > -1 ? this._parent : null;
        },
        get root() {
          return this._stage && this._stage._root;
        },
        get rotation() {
          return this._rotation;
        },
        set rotation(val) {
          val %= 360;
          if (val > 180) {
            val -= 360;
          }
          if (val === this._rotation)
            return;
          this._invalidate();
          this._invalidateTransform();
          this._rotation = val;
          var u, v;
          switch (val) {
          case 0:
          case 360:
            u = 1, v = 0;
            break;
          case 90:
          case -270:
            u = 0, v = 1;
            break;
          case 180:
          case -180:
            u = -1, v = 0;
            break;
          case 270:
          case -90:
            u = 0, v = -1;
            break;
          default:
            var angle = this._rotation / 180 * Math.PI;
            u = Math.cos(angle);
            v = Math.sin(angle);
            break;
          }
          this._rotationCos = u;
          this._rotationSin = v;
          var m = this._currentTransform;
          m.a = u * this._scaleX;
          m.b = v * this._scaleX;
          m.c = -v * this._scaleY;
          m.d = u * this._scaleY;
          this._animated = false;
        },
        get rotationX() {
          return 0;
        },
        set rotationX(val) {
          somewhatImplemented('DisplayObject.rotationX');
        },
        get rotationY() {
          return 0;
        },
        set rotationY(val) {
          somewhatImplemented('DisplayObject.rotationY');
        },
        get rotationZ() {
          return this.rotation;
        },
        set rotationZ(val) {
          this.rotation = val;
          somewhatImplemented('DisplayObject.rotationZ');
        },
        get stage() {
          return this._stage;
        },
        get scaleX() {
          return this._scaleX;
        },
        set scaleX(val) {
          if (val === this._scaleX)
            return;
          this._invalidate();
          this._invalidateTransform();
          this._scaleX = val;
          var m = this._currentTransform;
          m.a = this._rotationCos * val;
          m.b = this._rotationSin * val;
          this._animated = false;
        },
        get scaleY() {
          return this._scaleY;
        },
        set scaleY(val) {
          if (val === this._scaleY)
            return;
          this._invalidate();
          this._invalidateTransform();
          this._scaleY = val;
          var m = this._currentTransform;
          m.c = -this._rotationSin * val;
          m.d = this._rotationCos * val;
          this._animated = false;
        },
        get scaleZ() {
          return 1;
        },
        set scaleZ(val) {
          somewhatImplemented('DisplayObject.scaleZ');
        },
        get scale9Grid() {
          return this._scale9Grid;
        },
        set scale9Grid(val) {
          somewhatImplemented('DisplayObject.scale9Grid');
          this._scale9Grid = val;
          this._animated = false;
        },
        get scrollRect() {
          return this._scrollRect;
        },
        set scrollRect(val) {
          somewhatImplemented('DisplayObject.scrollRect');
          this._scrollRect = val;
        },
        get transform() {
          return new flash.geom.Transform(this);
        },
        set transform(val) {
          var transform = this.transform;
          transform.colorTransform = val.colorTransform;
          if (val.matrix3D) {
            transform.matrix3D = val.matrix3D;
          } else {
            transform.matrix = val.matrix;
          }
        },
        get visible() {
          return this._visible;
        },
        set visible(val) {
          if (val === this._visible)
            return;
          this._invalidate();
          this._visible = val;
          this._animated = false;
        },
        get width() {
          var bounds = this._getContentBounds();
          var t = this._currentTransform;
          return Math.abs(t.a) * (bounds.xMax - bounds.xMin) + Math.abs(t.c) * (bounds.yMax - bounds.yMin) | 0;
        },
        set width(val) {
          if (val < 0) {
            return;
          }
          var u = Math.abs(this._rotationCos);
          var v = Math.abs(this._rotationSin);
          var bounds = this._getContentBounds();
          var baseWidth = u * (bounds.xMax - bounds.xMin) + v * (bounds.yMax - bounds.yMin);
          if (!baseWidth) {
            return;
          }
          var baseHeight = v * (bounds.xMax - bounds.xMin) + u * (bounds.yMax - bounds.yMin);
          this.scaleY = this.height / baseHeight;
          this.scaleX = val / baseWidth;
        },
        get x() {
          return this._currentTransform.tx;
        },
        set x(val) {
          if (val === this._currentTransform.tx) {
            return;
          }
          this._invalidate();
          this._invalidateTransform();
          this._currentTransform.tx = val;
          this._animated = false;
        },
        get y() {
          return this._currentTransform.ty;
        },
        set y(val) {
          if (val === this._currentTransform.ty) {
            return;
          }
          this._invalidate();
          this._invalidateTransform();
          this._currentTransform.ty = val;
          this._animated = false;
        },
        get z() {
          return 0;
        },
        set z(val) {
          somewhatImplemented('DisplayObject.z');
        },
        _getContentBounds: function () {
          var bounds = this._bounds;
          if (bounds.invalid) {
            var bbox = this._bbox;
            var xMin = Number.MAX_VALUE;
            var xMax = Number.MIN_VALUE;
            var yMin = Number.MAX_VALUE;
            var yMax = Number.MIN_VALUE;
            if (bbox) {
              xMin = bbox.xMin;
              xMax = bbox.xMax;
              yMin = bbox.yMin;
              yMax = bbox.yMax;
            } else {
              var children = this._children;
              var numChildren = children.length;
              for (var i = 0; i < numChildren; i++) {
                var child = children[i];
                if (!flash.display.DisplayObject.class.isInstanceOf(child)) {
                  continue;
                }
                var b = child.getBounds(this);
                var x1 = b.xMin;
                var y1 = b.yMin;
                var x2 = b.xMax;
                var y2 = b.yMax;
                xMin = Math.min(xMin, x1, x2);
                xMax = Math.max(xMax, x1, x2);
                yMin = Math.min(yMin, y1, y2);
                yMax = Math.max(yMax, y1, y2);
              }
              if (this._graphics) {
                var b = this._graphics._getBounds(true);
                if (b.xMin !== b.xMax && b.yMin !== b.yMax) {
                  var x1 = b.xMin;
                  var y1 = b.yMin;
                  var x2 = b.xMax;
                  var y2 = b.yMax;
                  xMin = Math.min(xMin, x1, x2);
                  xMax = Math.max(xMax, x1, x2);
                  yMin = Math.min(yMin, y1, y2);
                  yMax = Math.max(yMax, y1, y2);
                }
              }
            }
            if (xMin === Number.MAX_VALUE) {
              xMin = xMax = yMin = yMax = 0;
            }
            bounds.xMin = xMin;
            bounds.xMax = xMax;
            bounds.yMin = yMin;
            bounds.yMax = yMax;
            bounds.invalid = false;
          }
          return bounds;
        },
        _getRegion: function getRegion(targetCoordSpace) {
          var b;
          var filters = this._filters;
          if (filters.length) {
            var xMin = Number.MAX_VALUE;
            var xMax = Number.MIN_VALUE;
            var yMin = Number.MAX_VALUE;
            var yMax = Number.MIN_VALUE;
            if (this._graphics) {
              b = this._graphics._getBounds(true);
              if (b) {
                xMin = b.xMin;
                xMax = b.xMax;
                yMin = b.yMin;
                yMax = b.yMax;
              }
            }
            var children = this._children;
            for (var i = 0; i < children.length; i++) {
              var child = children[i];
              b = children[i]._getRegion(this);
              if (b.xMin < xMin) {
                xMin = b.xMin;
              }
              if (b.xMax > xMax) {
                xMax = b.xMax;
              }
              if (b.yMin < yMin) {
                yMin = b.yMin;
              }
              if (b.yMax > yMax) {
                yMax = b.yMax;
              }
            }
            if (xMin === Number.MAX_VALUE) {
              return {
                xMin: 0,
                xMax: 0,
                yMin: 0,
                yMax: 0
              };
            }
            b = {
              xMin: xMin,
              xMax: xMax,
              yMin: yMin,
              yMax: yMax
            };
            for (var i = 0; i < filters.length; i++) {
              filters[i]._updateFilterBounds(b);
            }
          } else {
            b = this._graphics ? this._graphics._getBounds(true) : this._getContentBounds();
          }
          return this._getTransformedRect(b, targetCoordSpace);
        },
        getBounds: function (targetCoordSpace) {
          return this._getTransformedRect(this._getContentBounds(), targetCoordSpace);
        },
        _getTransformedRect: function (rect, targetCoordSpace) {
          if (!targetCoordSpace || targetCoordSpace === this) {
            return rect;
          }
          var xMin = rect.xMin;
          var xMax = rect.xMax;
          var yMin = rect.yMin;
          var yMax = rect.yMax;
          if (xMax - xMin === 0 || yMax - yMin === 0) {
            return {
              xMin: 0,
              yMin: 0,
              xMax: 0,
              yMax: 0
            };
          }
          var m = targetCoordSpace && !flash.display.DisplayObject.class.isInstanceOf(targetCoordSpace) ? targetCoordSpace : this._getConcatenatedTransform(targetCoordSpace, false);
          var x0 = m.a * xMin + m.c * yMin + m.tx | 0;
          var y0 = m.b * xMin + m.d * yMin + m.ty | 0;
          var x1 = m.a * xMax + m.c * yMin + m.tx | 0;
          var y1 = m.b * xMax + m.d * yMin + m.ty | 0;
          var x2 = m.a * xMax + m.c * yMax + m.tx | 0;
          var y2 = m.b * xMax + m.d * yMax + m.ty | 0;
          var x3 = m.a * xMin + m.c * yMax + m.tx | 0;
          var y3 = m.b * xMin + m.d * yMax + m.ty | 0;
          var tmp = 0;
          if (x0 > x1) {
            tmp = x0;
            x0 = x1;
            x1 = tmp;
          }
          if (x2 > x3) {
            tmp = x2;
            x2 = x3;
            x3 = tmp;
          }
          xMin = x0 < x2 ? x0 : x2;
          xMax = x1 > x3 ? x1 : x3;
          if (y0 > y1) {
            tmp = y0;
            y0 = y1;
            y1 = tmp;
          }
          if (y2 > y3) {
            tmp = y2;
            y2 = y3;
            y3 = tmp;
          }
          yMin = y0 < y2 ? y0 : y2;
          yMax = y1 > y3 ? y1 : y3;
          return {
            xMin: xMin,
            yMin: yMin,
            xMax: xMax,
            yMax: yMax
          };
        },
        hitTestObject: function (obj) {
          return this._hitTest(false, 0, 0, false, obj);
        },
        hitTestPoint: function (x, y, shapeFlag) {
          return this._hitTest(true, x, y, shapeFlag, null);
        },
        destroy: function () {
          if (this._destroyed) {
            return;
          }
          this._destroyed = true;
          this.cleanupBroadcastListeners();
        },
        cleanupBroadcastListeners: function () {
          var listenerLists = this._listeners;
          for (var type in listenerLists) {
            avm2.systemDomain.onMessage.unregister(type, this._onBroadcastMessage);
          }
        }
      };
    var desc = Object.getOwnPropertyDescriptor;
    def.__glue__ = {
      native: {
        instance: {
          root: desc(def, 'root'),
          stage: desc(def, 'stage'),
          name: desc(def, 'name'),
          parent: desc(def, 'parent'),
          mask: desc(def, 'mask'),
          visible: desc(def, 'visible'),
          x: {
            get: function x() {
              return this.x / 20;
            },
            set: function x(value) {
              this.x = value * 20 | 0;
            }
          },
          y: {
            get: function y() {
              return this.y / 20;
            },
            set: function y(value) {
              this.y = value * 20 | 0;
            }
          },
          z: {
            get: function z() {
              return this.z / 20;
            },
            set: function z(value) {
              this.z = value * 20 | 0;
            }
          },
          scaleX: desc(def, 'scaleX'),
          scaleY: desc(def, 'scaleY'),
          scaleZ: desc(def, 'scaleZ'),
          mouseX: {
            get: function mouseX() {
              return this.mouseX / 20;
            },
            set: function mouseX(value) {
              this.mouseX = value * 20 | 0;
            }
          },
          mouseY: {
            get: function mouseY() {
              return this.mouseY / 20;
            },
            set: function mouseY(value) {
              this.mouseY = value * 20 | 0;
            }
          },
          rotation: desc(def, 'rotation'),
          rotationX: desc(def, 'rotationX'),
          rotationY: desc(def, 'rotationY'),
          rotationZ: desc(def, 'rotationZ'),
          alpha: desc(def, 'alpha'),
          width: {
            get: function width() {
              return this.width / 20;
            },
            set: function width(value) {
              this.width = value * 20 | 0;
            }
          },
          height: {
            get: function height() {
              return this.height / 20;
            },
            set: function height(value) {
              this.height = value * 20 | 0;
            }
          },
          _hitTest: function (use_xy, x, y, useShape, hitTestObject) {
            x = x * 20 | 0;
            y = y * 20 | 0;
            return this._hitTest(use_xy, x, y, useShape, hitTestObject);
          },
          cacheAsBitmap: desc(def, 'cacheAsBitmap'),
          opaqueBackground: desc(def, 'opaqueBackground'),
          scrollRect: desc(def, 'scrollRect'),
          filters: desc(def, 'filters'),
          blendMode: desc(def, 'blendMode'),
          transform: desc(def, 'transform'),
          scale9Grid: desc(def, 'scale9Grid'),
          loaderInfo: desc(def, 'loaderInfo'),
          accessibilityProperties: desc(def, 'accessibilityProperties'),
          globalToLocal: function (pt) {
            point.x = pt.x * 20 | 0;
            point.y = pt.y * 20 | 0;
            this._applyConcatenatedInverseTransform(point);
            return new flash.geom.Point(point.x / 20, point.y / 20);
          },
          localToGlobal: function (pt) {
            point.x = pt.x * 20 | 0;
            point.y = pt.y * 20 | 0;
            this._applyCurrentTransform(point);
            return new flash.geom.Point(point.x / 20, point.y / 20);
          },
          getBounds: function (targetCoordSpace) {
            var bounds = this.getBounds(targetCoordSpace);
            return new flash.geom.Rectangle(bounds.xMin / 20, bounds.yMin / 20, (bounds.xMax - bounds.xMin) / 20, (bounds.yMax - bounds.yMin) / 20);
          },
          getRect: function (targetCoordSpace) {
            somewhatImplemented('DisplayObject.getRect');
            var bounds = this.getBounds(targetCoordSpace);
            return new flash.geom.Rectangle(bounds.xMin / 20, bounds.yMin / 20, (bounds.xMax - bounds.xMin) / 20, (bounds.yMax - bounds.yMin) / 20);
          }
        }
      }
    };
    return def;
  }.call(this);
var DisplayObjectContainerDefinition = function () {
    var def = {
        get mouseChildren() {
          return this._mouseChildren;
        },
        set mouseChildren(val) {
          this._mouseChildren = val;
        },
        get numChildren() {
          return this._children.length;
        },
        get tabChildren() {
          return this._tabChildren;
        },
        set tabChildren(val) {
          this._tabChildren = val;
        },
        get textSnapshot() {
          notImplemented();
        },
        addChild: function (child) {
          return this.addChildAt(child, this._children.length);
        },
        addChildAt: function (child, index) {
          if (child === this) {
            throwError('ArgumentError', Errors.CantAddSelfError);
          }
          if (child._parent === this) {
            return this.setChildIndex(child, index);
          }
          var children = this._children;
          if (index < 0 || index > children.length) {
            throwError('RangeError', Errors.ParamRangeError);
          }
          if (child._index > -1) {
            var LoaderClass = avm2.systemDomain.getClass('flash.display.Loader');
            if (LoaderClass.isInstanceOf(child._parent)) {
              def.removeChild.call(child._parent, child);
            } else {
              child._parent.removeChild(child);
            }
          }
          if (!this._sparse) {
            for (var i = children.length; i && i > index; i--) {
              children[i - 1]._index++;
            }
          }
          children.splice(index, 0, child);
          child._invalidateTransform();
          child._owned = false;
          child._parent = this;
          child._stage = this._stage;
          child._index = index;
          child._dispatchEvent('added', undefined, true);
          if (this._stage) {
            this._stage._addToStage(child);
          }
          return child;
        },
        areInaccessibleObjectsUnderPoint: function (pt) {
          notImplemented();
        },
        contains: function (child) {
          return child._parent === this;
        },
        getChildAt: function (index) {
          var children = this._children;
          if (index < 0 || index > children.length) {
            throwError('RangeError', Errors.ParamRangeError);
          }
          var child = children[index];
          if (!flash.display.DisplayObject.class.isInstanceOf(child)) {
            return null;
          }
          return child;
        },
        getChildByName: function (name) {
          var children = this._children;
          for (var i = 0, n = children.length; i < n; i++) {
            var child = children[i];
            if (child.name === name) {
              return this.getChildAt(i);
            }
          }
          return null;
        },
        getChildIndex: function (child) {
          if (child._parent !== this) {
            throwError('ArgumentError', Errors.NotAChildError);
          }
          return this._sparse ? this._children.indexOf(child) : child._index;
        },
        getObjectsUnderPoint: function (pt) {
          notImplemented();
        },
        removeChild: function (child) {
          if (child._parent !== this) {
            throwError('ArgumentError', Errors.NotAChildError);
          }
          return this.removeChildAt(this.getChildIndex(child));
        },
        removeChildAt: function (index) {
          var children = this._children;
          if (index < 0 || index >= children.length) {
            throwError('RangeError', Errors.ParamRangeError);
          }
          var child = children[index];
          child._dispatchEvent('removed', undefined, true);
          if (this._stage) {
            this._stage._removeFromStage(child);
          }
          if (!this._sparse) {
            for (var i = children.length; i && i > index; i--) {
              children[i - 1]._index--;
            }
          }
          children.splice(index, 1);
          child._invalidateTransform();
          child._owned = false;
          child._parent = null;
          child._index = -1;
          return child;
        },
        setChildIndex: function (child, index) {
          if (child._parent !== this) {
            throwError('ArgumentError', Errors.NotAChildError);
          }
          var currentIndex = this.getChildIndex(child);
          if (currentIndex === index) {
            return;
          }
          var children = this._children;
          if (index < 0 || index > children.length) {
            throwError('RangeError', Errors.ParamRangeError);
          }
          children.splice(currentIndex, 1);
          children.splice(index, 0, child);
          if (!this._sparse) {
            var i = currentIndex < index ? currentIndex : index;
            while (i < children.length) {
              children[i]._index = i++;
            }
          }
          child._owned = false;
          child._invalidate();
          return child;
        },
        removeChildren: function (beginIndex, endIndex) {
          beginIndex = arguments.length < 1 ? 0 : beginIndex | 0;
          endIndex = arguments.length < 2 ? 2147483647 : endIndex | 0;
          var numChildren = this._children.length;
          if (beginIndex < 0 || endIndex < 0 || endIndex < beginIndex) {
            throwError('RangeError', Errors.ParamRangeError);
          }
          if (numChildren === 0) {
            return;
          }
          if (endIndex > numChildren - 1) {
            endIndex = numChildren - 1;
          }
          var count = endIndex - beginIndex + 1;
          while (count--) {
            this.removeChildAt(beginIndex);
          }
        },
        swapChildren: function (child1, child2) {
          if (child1._parent !== this || child2._parent !== this) {
            throwError('ArgumentError', Errors.NotAChildError);
          }
          this.swapChildrenAt(this.getChildIndex(child1), this.getChildIndex(child2));
        },
        swapChildrenAt: function (index1, index2) {
          var children = this._children;
          var numChildren = children.length;
          if (index1 < 0 || index1 > numChildren || index2 < 0 || index2 > numChildren) {
            throwError('RangeError', Errors.ParamRangeError);
          }
          var child1 = children[index1];
          var child2 = children[index2];
          children[index1] = child2;
          children[index2] = child1;
          child1._index = index2;
          child2._index = index1;
          child1._owned = false;
          child2._owned = false;
          child1._invalidate();
          child2._invalidate();
        },
        destroy: function () {
          if (this._destroyed) {
            return;
          }
          this._destroyed = true;
          this._children.forEach(function (child) {
            if (child.destroy) {
              child.destroy();
            }
          });
          this.cleanupBroadcastListeners();
        }
      };
    var desc = Object.getOwnPropertyDescriptor;
    def.initialize = function () {
      this._mouseChildren = true;
      this._tabChildren = true;
      this._sparse = false;
      this._isContainer = true;
    };
    def.__glue__ = {
      native: {
        instance: {
          numChildren: desc(def, 'numChildren'),
          tabChildren: desc(def, 'tabChildren'),
          mouseChildren: desc(def, 'mouseChildren'),
          textSnapshot: desc(def, 'textSnapshot'),
          addChild: def.addChild,
          addChildAt: def.addChildAt,
          removeChild: def.removeChild,
          removeChildAt: def.removeChildAt,
          getChildIndex: def.getChildIndex,
          setChildIndex: def.setChildIndex,
          getChildAt: def.getChildAt,
          getChildByName: def.getChildByName,
          contains: def.contains,
          swapChildrenAt: def.swapChildrenAt,
          swapChildren: def.swapChildren,
          removeChildren: def.removeChildren
        }
      }
    };
    return def;
  }.call(this);
var FrameLabelDefinition = function () {
    return {
      __class__: 'flash.display.FrameLabel',
      initialize: function () {
      },
      __glue__: {
        native: {
          static: {},
          instance: {
            ctor: function ctor(name, frame) {
              this._name = name;
              this._frame = frame;
            },
            name: {
              get: function name() {
                return this._name;
              }
            },
            frame: {
              get: function frame() {
                return this._frame;
              }
            }
          }
        }
      }
    };
  }.call(this);
var GraphicsDefinition = function () {
    var GRAPHICS_PATH_WINDING_EVEN_ODD = 'evenOdd';
    var GRAPHICS_PATH_WINDING_NON_ZERO = 'nonZero';
    var def = {
        __class__: 'flash.display.Graphics',
        initialize: function () {
          this._paths = [];
          this.beginPath();
          this._bitmap = null;
          this._parent = 0;
          this.bbox = null;
          this.strokeBbox = null;
        },
        _invalidate: function () {
          this.bbox = null;
          this.strokeBbox = null;
          this._parent._invalidate();
          this._parent._invalidateBounds();
        },
        beginPath: function () {
          var oldPath = this._currentPath;
          if (oldPath && (oldPath.commands.length === 0 || oldPath.commands.length === 1 && oldPath.commands[0] === SHAPE_MOVE_TO)) {
            return;
          }
          var path = this._currentPath = new ShapePath(null, null);
          this._paths.push(path);
          if (oldPath) {
            path.fillStyle = oldPath.fillStyle;
            path.lineStyle = oldPath.lineStyle;
            path.fillRule = oldPath.fillRule;
          }
        },
        _drawPathObject: function (path) {
          if (path.__class__ === 'flash.display.GraphicsPath')
            this.drawPath(path.commands, path.data, path.winding);
          else if (path.__class__ === 'flash.display.GraphicsTrianglePath')
            this.drawTriangles(path.vertices, path.indices, path.uvtData, path.culling);
        },
        draw: function (ctx, clip, ratio, colorTransform) {
          var paths = this._paths;
          for (var i = 0; i < paths.length; i++) {
            paths[i].draw(ctx, clip, ratio, colorTransform);
          }
        },
        beginFill: function (color, alpha) {
          if (alpha === undefined)
            alpha = 1;
          this.beginPath();
          this._currentPath.fillStyle = alpha ? {
            style: rgbIntAlphaToStr(color, alpha)
          } : null;
        },
        beginGradientFill: function (type, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPos) {
          var style = createGradientStyle(type, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPos);
          this.beginPath();
          this._currentPath.fillStyle = style;
        },
        beginBitmapFill: function (bitmap, matrix, repeat, smooth) {
          this.beginPath();
          repeat = repeat !== false;
          this._currentPath.fillStyle = createPatternStyle(bitmap, matrix, repeat, !(!smooth));
        },
        clear: function () {
          this._invalidate();
          this._paths = [];
          this._currentPath = null;
          this.beginPath();
        },
        copyFrom: function (sourceGraphics) {
          notImplemented('Graphics#copyFrom');
        },
        cubicCurveTo: function (cp1x, cp1y, cp2x, cp2y, x, y) {
          this._invalidate();
          this._currentPath.cubicCurveTo(cp1x * 20 | 0, cp1y * 20 | 0, cp2x * 20 | 0, cp2y * 20 | 0, x * 20 | 0, y * 20 | 0);
        },
        curveTo: function (cpx, cpy, x, y) {
          this._invalidate();
          this._currentPath.curveTo(cpx * 20 | 0, cpy * 20 | 0, x * 20 | 0, y * 20 | 0);
        },
        drawCircle: function (x, y, radius) {
          var radius2 = radius * 2;
          this.drawRoundRect(x - radius, y - radius, radius2, radius2, radius2, radius2);
        },
        drawEllipse: function (x, y, width, height) {
          this.drawRoundRect(x, y, width, height, width, height);
        },
        drawPath: function (commands, data, winding) {
          this._invalidate();
          this.beginPath();
          this._currentPath.fillRule = winding || GRAPHICS_PATH_WINDING_EVEN_ODD;
          this._currentPath.commands = commands;
          this._currentPath.data = data;
        },
        drawRect: function (x, y, w, h) {
          if (isNaN(w + h))
            throwError('ArgumentError', Errors.InvalidParamError);
          this._invalidate();
          this._currentPath.rect(x * 20 | 0, y * 20 | 0, w * 20 | 0, h * 20 | 0);
        },
        drawRoundRect: function (x, y, w, h, ellipseWidth, ellipseHeight) {
          if (isNaN(w + h + ellipseWidth) || ellipseHeight !== undefined && isNaN(ellipseHeight)) {
            throwError('ArgumentError', Errors.InvalidParamError);
          }
          this._invalidate();
          if (ellipseHeight === undefined) {
            ellipseHeight = ellipseWidth;
          }
          x = x * 20 | 0;
          y = y * 20 | 0;
          w = w * 20 | 0;
          h = h * 20 | 0;
          if (!ellipseHeight || !ellipseWidth) {
            this._currentPath.rect(x, y, w, h);
            return;
          }
          var radiusX = ellipseWidth / 2 * 20 | 0;
          var radiusY = ellipseHeight / 2 * 20 | 0;
          var hw = w / 2 | 0;
          var hh = h / 2 | 0;
          if (radiusX > hw) {
            radiusX = hw;
          }
          if (radiusY > hh) {
            radiusY = hh;
          }
          if (hw === radiusX && hh === radiusY) {
            if (radiusX === radiusY)
              this._currentPath.circle(x + radiusX, y + radiusY, radiusX);
            else
              this._currentPath.ellipse(x + radiusX, y + radiusY, radiusX, radiusY);
            return;
          }
          var right = x + w;
          var bottom = y + h;
          var xlw = x + radiusX;
          var xrw = right - radiusX;
          var ytw = y + radiusY;
          var ybw = bottom - radiusY;
          this._currentPath.moveTo(right, ybw);
          this._currentPath.curveTo(right, bottom, xrw, bottom);
          this._currentPath.lineTo(xlw, bottom);
          this._currentPath.curveTo(x, bottom, x, ybw);
          this._currentPath.lineTo(x, ytw);
          this._currentPath.curveTo(x, y, xlw, y);
          this._currentPath.lineTo(xrw, y);
          this._currentPath.curveTo(right, y, right, ytw);
          this._currentPath.lineTo(right, ybw);
        },
        drawRoundRectComplex: function (x, y, w, h, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius) {
          if (isNaN(w + h + topLeftRadius + topRightRadius + bottomLeftRadius + bottomRightRadius)) {
            throwError('ArgumentError', Errors.InvalidParamError);
          }
          this._invalidate();
          x = x * 20 | 0;
          y = y * 20 | 0;
          w = w * 20 | 0;
          h = h * 20 | 0;
          if (!topLeftRadius && !topRightRadius && !bottomLeftRadius && !bottomRightRadius) {
            this._currentPath.rect(x, y, w, h);
            return;
          }
          topLeftRadius = topLeftRadius * 20 | 0;
          topRightRadius = topRightRadius * 20 | 0;
          bottomLeftRadius = bottomLeftRadius * 20 | 0;
          bottomRightRadius = bottomRightRadius * 20 | 0;
          var right = x + w;
          var bottom = y + h;
          var xtl = x + topLeftRadius;
          this._currentPath.moveTo(right, bottom - bottomRightRadius);
          this._currentPath.curveTo(right, bottom, right - bottomRightRadius, bottom);
          this._currentPath.lineTo(x + bottomLeftRadius, bottom);
          this._currentPath.curveTo(x, bottom, x, bottom - bottomLeftRadius);
          this._currentPath.lineTo(x, y + topLeftRadius);
          this._currentPath.curveTo(x, y, xtl, y);
          this._currentPath.lineTo(right - topRightRadius, y);
          this._currentPath.curveTo(right, y, right, y + topRightRadius);
          this._currentPath.lineTo(right, bottom - bottomRightRadius);
        },
        drawTriangles: function (vertices, indices, uvtData, cullingStr) {
          if (vertices === null || vertices.length === 0) {
            return;
          }
          var numVertices = vertices.length / 2;
          var numTriangles = 0;
          if (indices) {
            if (indices.length % 3) {
              throwError('ArgumentError', Errors.InvalidParamError);
            } else {
              numTriangles = indices.length / 3;
            }
          } else {
            if (vertices.length % 6) {
              throwError('ArgumentError', Errors.InvalidParamError);
            } else {
              numTriangles = vertices.length / 6;
            }
          }
          var numStrides = 0;
          if (uvtData) {
            if (uvtData.length == numVertices * 2) {
              numStrides = 2;
            } else if (uvtData.length == numVertices * 3) {
              numStrides = 3;
            } else {
              throwError('ArgumentError', Errors.InvalidParamError);
            }
          }
          var culling = 0;
          if (cullingStr === 'none') {
            culling = 0;
          } else if (cullingStr === 'negative') {
            culling = -1;
          } else if (cullingStr === 'positive') {
            culling = 1;
          } else {
            throwError('ArgumentError', Errors.InvalidEnumError, 'culling');
          }
          notImplemented('Graphics#drawTriangles');
        },
        endFill: function () {
          this.beginPath();
          this._currentPath.fillStyle = null;
        },
        lineBitmapStyle: function (bitmap, matrix, repeat, smooth) {
          this.beginPath();
          this._currentPath.lineStyle = createPatternStyle(bitmap, matrix, repeat, smooth);
        },
        lineGradientStyle: function (type, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPos) {
          var style = createGradientStyle(type, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPos);
          this.beginPath();
          this._currentPath.lineStyle = style;
        },
        lineStyle: function (width, color, alpha, pxHinting, scale, cap, joint, mlimit) {
          this.beginPath();
          if (width) {
            if (alpha === undefined)
              alpha = 1;
            if (mlimit === undefined)
              mlimit = 3;
            this._currentPath.lineStyle = {
              style: rgbIntAlphaToStr(color, alpha),
              lineCap: cap || 'round',
              lineJoin: cap || 'round',
              width: width * 20 | 0,
              miterLimit: mlimit * 2
            };
          } else {
            this._currentPath.lineStyle = null;
          }
        },
        lineTo: function (x, y) {
          this._invalidate();
          this._currentPath.lineTo(x * 20 | 0, y * 20 | 0);
        },
        moveTo: function (x, y) {
          this._currentPath.moveTo(x * 20 | 0, y * 20 | 0);
        },
        _getBounds: function (includeStroke) {
          var bbox = includeStroke ? this.strokeBbox : this.bbox;
          if (bbox) {
            return bbox;
          }
          var subpaths = this._paths;
          var xMins = [], yMins = [], xMaxs = [], yMaxs = [];
          for (var i = 0, n = subpaths.length; i < n; i++) {
            var path = subpaths[i];
            if (path.commands.length) {
              var b = path.getBounds(includeStroke);
              if (b) {
                xMins.push(b.xMin);
                yMins.push(b.yMin);
                xMaxs.push(b.xMax);
                yMaxs.push(b.yMax);
              }
            }
          }
          if (xMins.length === 0) {
            bbox = {
              xMin: 0,
              yMin: 0,
              xMax: 0,
              yMax: 0
            };
          } else {
            bbox = {
              xMin: Math.min.apply(Math, xMins),
              yMin: Math.min.apply(Math, yMins),
              xMax: Math.max.apply(Math, xMaxs),
              yMax: Math.max.apply(Math, yMaxs)
            };
          }
          if (includeStroke) {
            this.strokeBbox = bbox;
          } else {
            this.bbox = bbox;
          }
          return bbox;
        }
      };
    def.__glue__ = {
      native: {
        instance: {
          beginFill: def.beginFill,
          beginGradientFill: def.beginGradientFill,
          beginBitmapFill: def.beginBitmapFill,
          beginFillObject: def.beginFillObject,
          beginStrokeObject: def.beginStrokeObject,
          clear: def.clear,
          copyFrom: def.copyFrom,
          cubicCurveTo: def.cubicCurveTo,
          curveTo: def.curveTo,
          drawCircle: def.drawCircle,
          drawEllipse: def.drawEllipse,
          drawPath: def.drawPath,
          drawRect: def.drawRect,
          drawRoundRect: def.drawRoundRect,
          drawRoundRectComplex: def.drawRoundRectComplex,
          drawTriangles: def.drawTriangles,
          endFill: def.endFill,
          lineBitmapStyle: def.lineBitmapStyle,
          lineGradientStyle: def.lineGradientStyle,
          lineStyle: def.lineStyle,
          moveTo: def.moveTo,
          lineTo: def.lineTo
        }
      }
    };
    return def;
  }.call(this);
function createPatternStyle(bitmap, matrix, repeat, smooth) {
  var repeatStyle = repeat === false ? 'no-repeat' : 'repeat';
  var pattern = factoryCtx.createPattern(bitmap._drawable, repeatStyle);
  var transform = matrix ? {
      a: matrix.a,
      b: matrix.b,
      c: matrix.c,
      d: matrix.d,
      e: matrix.tx,
      f: matrix.ty
    } : {
      a: 1,
      b: 0,
      c: 0,
      d: 1,
      e: 0,
      f: 0
    };
  return {
    style: pattern,
    transform: transform,
    smooth: smooth
  };
}
function createGradientStyle(type, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPos) {
  type === null || type === undefined && throwError('TypeError', Errors.NullPointerError, 'type');
  colors === null || type === undefined && throwError('TypeError', Errors.NullPointerError, 'colors');
  if (!(type === 'linear' || type === 'radial')) {
    throwError('ArgumentError', Errors.InvalidEnumError, 'type');
  }
  var colorStops = [];
  for (var i = 0, n = colors.length; i < n; i++) {
    colorStops.push({
      ratio: ratios[i] / 255,
      color: rgbIntAlphaToStr(colors[i], alphas[i])
    });
  }
  var gradientConstructor;
  if (type === 'linear') {
    gradientConstructor = buildLinearGradientFactory(colorStops);
  } else {
    gradientConstructor = buildRadialGradientFactory(focalPos || 0, colorStops);
  }
  var scale = 819.2;
  var transform = matrix ? {
      a: scale * matrix.a,
      b: scale * matrix.b,
      c: scale * matrix.c,
      d: scale * matrix.d,
      e: matrix.tx,
      f: matrix.ty
    } : {
      a: scale,
      b: 0,
      c: 0,
      d: scale,
      e: 0,
      f: 0
    };
  return {
    style: gradientConstructor,
    transform: transform
  };
}
function drawGraphicsData(data) {
  if (data === null) {
    return;
  }
  for (var i = 0; i < data.length; i++) {
    var item = data[i];
    if (flash.display.IGraphicsPath.class.isInstanceOf(item)) {
      this._drawPathObject(item);
    } else if (flash.display.IGraphicsStroke.class.isInstanceOf(item)) {
      this.beginStrokeObject(item);
    } else if (flash.display.IGraphicsFill.class.isInstanceOf(item)) {
      this.beginFillObject(item);
    }
  }
}
var InteractiveObjectDefinition = function () {
    var def = {
        initialize: function () {
          this._contextMenu = null;
          this._doubleClickEnabled = false;
          this._focusRect = null;
          this._mouseEnabled = true;
          this._tabEnabled = false;
        },
        get accessibilityImplementation() {
          return null;
        },
        set accessibilityImplementation(val) {
          somewhatImplemented('accessibilityImplementation');
        },
        get contextMenu() {
          somewhatImplemented('contextMenu');
          return this._contextMenu;
        },
        set contextMenu(val) {
          somewhatImplemented('contextMenu');
          this._contextMenu = val;
        },
        get doubleClickEnabled() {
          return this._doubleClickEnabled;
        },
        set doubleClickEnabled(val) {
          this._doubleClickEnabled = val;
        },
        get focusRect() {
          return this._focusRect;
        },
        set focusRect(val) {
          this._focusRect = val;
        },
        get mouseEnabled() {
          return this._mouseEnabled;
        },
        set mouseEnabled(val) {
          this._mouseEnabled = val;
        },
        get needsSoftKeyboard() {
          return false;
        },
        set needsSoftKeyboard(val) {
          notImplemented();
        },
        get softKeyboardInputAreaOfInterest() {
          return null;
        },
        set softKeyboardInputAreaOfInterest(val) {
          notImplemented();
        },
        get tabEnabled() {
          return this._tabEnabled;
        },
        set tabEnabled(val) {
          var old = this._tabEnabled;
          this._tabEnabled = val;
          if (old !== val) {
            var Event = flash.events.Event;
            this._dispatchEvent(new Event('tabEnabledChange', false, false));
          }
        },
        requestSoftKeyboard: function () {
          notImplemented();
        }
      };
    var desc = Object.getOwnPropertyDescriptor;
    def.__glue__ = {
      native: {
        instance: {
          tabEnabled: desc(def, 'tabEnabled'),
          tabIndex: {
            get: function tabIndex() {
              return this._tabIndex;
            },
            set: function tabIndex(index) {
              this._tabIndex = index;
            }
          },
          focusRect: desc(def, 'focusRect'),
          mouseEnabled: desc(def, 'mouseEnabled'),
          doubleClickEnabled: desc(def, 'doubleClickEnabled'),
          accessibilityImplementation: desc(def, 'accessibilityImplementation'),
          softKeyboardInputAreaOfInterest: desc(def, 'softKeyboardInputAreaOfInterest'),
          needsSoftKeyboard: desc(def, 'needsSoftKeyboard'),
          contextMenu: desc(def, 'contextMenu'),
          requestSoftKeyboard: def.requestSoftKeyboard
        }
      }
    };
    return def;
  }.call(this);
var $RELEASE = false;
var LoaderDefinition = function () {
    var WORKERS_ENABLED = true;
    var LOADER_PATH = true ? 'shumway-worker.js' : 'swf/resourceloader.js';
    var head = document.head;
    head.insertBefore(document.createElement('style'), head.firstChild);
    var style = document.styleSheets[0];
    var def = {
        __class__: 'flash.display.Loader',
        initialize: function () {
          this._contentLoaderInfo = new flash.display.LoaderInfo();
          this._contentLoaderInfo._loader = this;
          this._dictionary = {};
          this._dictionaryResolved = {};
          this._displayList = null;
          this._timeline = [];
          this._lastPromise = null;
          this._uncaughtErrorEvents = null;
          this._worker = null;
          var abc = AVM2.currentAbc();
          if (abc && abc.env.loader) {
            this._contentLoaderInfo._loaderURL = abc.env.loader._contentLoaderInfo._url;
          }
        },
        _commitData: function (data) {
          switch (data.command) {
          case 'init':
            this._init(data.result);
            break;
          case 'progress':
            this._updateProgress(data.result);
            break;
          case 'complete':
            var frameConstructed = new Promise(function (resolve) {
                avm2.systemDomain.onMessage.register('frameConstructed', function waitForFrame(type) {
                  if (type === 'frameConstructed') {
                    resolve();
                    avm2.systemDomain.onMessage.unregister('frameConstructed', waitForFrame);
                  }
                });
              });
            this._contentLoaderInfo._dispatchEvent('parsed');
            Promise.all([
              frameConstructed,
              this._lastPromise
            ]).then(function () {
              this._content._complete = true;
              this._contentLoaderInfo._dispatchEvent('complete');
            }.bind(this));
            var stats = data.stats;
            if (stats) {
              TelemetryService.reportTelemetry(stats);
            }
            this._worker && this._worker.terminate();
            break;
          case 'empty':
            this._lastPromise = Promise.resolve();
            break;
          case 'error':
            this._contentLoaderInfo._dispatchEvent('ioError', flash.events.IOErrorEvent);
            break;
          default:
            if (data.id === 0)
              break;
            if (data.isSymbol)
              this._commitSymbol(data);
            else if (data.type === 'frame')
              this._commitFrame(data);
            else if (data.type === 'image')
              this._commitImage(data);
            break;
          }
        },
        _updateProgress: function (state) {
          var loaderInfo = this._contentLoaderInfo;
          loaderInfo._bytesLoaded = state.bytesLoaded || 0;
          loaderInfo._bytesTotal = state.bytesTotal || 0;
          var event = new flash.events.ProgressEvent('progress', false, false, loaderInfo._bytesLoaded, loaderInfo._bytesTotal);
          loaderInfo._dispatchEvent(event);
        },
        _buildFrame: function (currentDisplayList, timeline, promiseQueue, frame, frameNum) {
          var loader = this;
          var dictionary = loader._dictionary;
          var dictionaryResolved = loader._dictionaryResolved;
          var displayList = {};
          var depths = [];
          var cmds = frame.depths;
          if (currentDisplayList) {
            var currentDepths = currentDisplayList.depths;
            for (var i = 0; i < currentDepths.length; i++) {
              var depth = currentDepths[i];
              if (cmds[depth] === null) {
                continue;
              }
              displayList[depth] = currentDisplayList[depth];
              depths.push(depth);
            }
          }
          for (var depth in cmds) {
            var cmd = cmds[depth];
            if (!cmd) {
              continue;
            }
            if (cmd.move) {
              var oldCmd = cmd;
              cmd = cloneObject(currentDisplayList[depth]);
              for (var prop in oldCmd) {
                var val = oldCmd[prop];
                if (val) {
                  cmd[prop] = val;
                }
              }
            }
            if (cmd.symbolId) {
              var itemPromise = dictionary[cmd.symbolId];
              if (itemPromise && !dictionaryResolved[cmd.symbolId]) {
                promiseQueue.push(itemPromise);
              }
              cmd = cloneObject(cmd);
              Object.defineProperty(cmd, 'symbolInfo', {
                get: function (dictionaryResolved, symbolId) {
                  return function () {
                    return dictionaryResolved[symbolId];
                  };
                }(dictionaryResolved, cmd.symbolId)
              });
            }
            if (!displayList[depth]) {
              depths.push(depth);
            }
            displayList[depth] = cmd;
          }
          depths.sort(sortNumeric);
          displayList.depths = depths;
          var i = frame.repeat;
          while (i--) {
            timeline.push(displayList);
          }
          return displayList;
        },
        _commitFrame: function (frame) {
          var abcBlocks = frame.abcBlocks;
          var actionBlocks = frame.actionBlocks;
          var initActionBlocks = frame.initActionBlocks;
          var exports = frame.exports;
          var symbolClasses = frame.symbolClasses;
          var sceneData = frame.sceneData;
          var loader = this;
          var dictionary = loader._dictionary;
          var loaderInfo = loader._contentLoaderInfo;
          var timeline = loader._timeline;
          var frameNum = timeline.length + 1;
          var framePromiseResolve;
          var framePromise = new Promise(function (resolve) {
              framePromiseResolve = resolve;
            });
          var labelName = frame.labelName;
          var prevPromise = this._lastPromise;
          this._lastPromise = framePromise;
          var promiseQueue = [
              prevPromise
            ];
          this._displayList = this._buildFrame(this._displayList, timeline, promiseQueue, frame, frameNum);
          var framesLoaded = timeline.length;
          if (frame.bgcolor)
            loaderInfo._backgroundColor = frame.bgcolor;
          else if (isNullOrUndefined(loaderInfo._backgroundColor))
            loaderInfo._backgroundColor = {
              red: 255,
              green: 255,
              blue: 255,
              alpha: 255
            };
          Promise.all(promiseQueue).then(function () {
            if (abcBlocks && loader._isAvm2Enabled) {
              var appDomain = avm2.applicationDomain;
              for (var i = 0, n = abcBlocks.length; i < n; i++) {
                var abc = new AbcFile(abcBlocks[i].data, 'abc_block_' + i);
                abc.env.loader = loader;
                if (abcBlocks[i].flags) {
                  appDomain.loadAbc(abc);
                } else {
                  appDomain.executeAbc(abc);
                }
              }
            }
            if (symbolClasses && loader._isAvm2Enabled) {
              var symbolClassesPromises = [];
              for (var i = 0, n = symbolClasses.length; i < n; i++) {
                var asset = symbolClasses[i];
                var symbolPromise = dictionary[asset.symbolId];
                if (!symbolPromise)
                  continue;
                symbolPromise.then(function (className) {
                  return function symbolPromiseResolved(symbolInfo) {
                    symbolInfo.className = className;
                    avm2.applicationDomain.getClass(className).setSymbol(symbolInfo.props);
                  };
                }(asset.className));
                symbolClassesPromises.push(symbolPromise);
              }
              return Promise.all(symbolClassesPromises);
            }
            if (exports && !loader._isAvm2Enabled) {
              var exportPromises = [];
              for (var i = 0, n = exports.length; i < n; i++) {
                var asset = exports[i];
                var symbolPromise = dictionary[asset.symbolId];
                if (!symbolPromise)
                  continue;
                symbolPromise.then(function (className) {
                  return function symbolPromiseResolved(symbolInfo) {
                    loader._avm1Context.addAsset(className, symbolInfo.props);
                  };
                }(asset.className));
                exportPromises.push(symbolPromise);
              }
              return Promise.all(exportPromises);
            }
          }).then(function () {
            var root = loader._content;
            var labelMap;
            if (!root) {
              var parent = loader._parent;
              true;
              var rootInfo = loader._dictionaryResolved[0];
              var rootClass = avm2.applicationDomain.getClass(rootInfo.className);
              root = rootClass.createAsSymbol({
                framesLoaded: framesLoaded,
                loader: loader,
                parent: parent || loader,
                index: parent ? 0 : -1,
                level: parent ? 0 : -1,
                timeline: timeline,
                totalFrames: rootInfo.props.totalFrames,
                stage: loader._stage,
                complete: frame.complete
              });
              if (!loader._isAvm2Enabled) {
                var avm1Context = loader._avm1Context;
                var _root = root;
                if (parent && parent !== loader._stage) {
                  var parentLoader = parent.loaderInfo._loader;
                  while (parentLoader._parent && parentLoader._parent !== loader._stage) {
                    parentLoader = parentLoader._parent.loaderInfo._loader;
                  }
                  if (parentLoader._isAvm2Enabled) {
                    somewhatImplemented('AVM1Movie');
                    this._worker && this._worker.terminate();
                    return;
                  }
                  _root = parentLoader._content;
                }
                var as2Object = _root._getAS2Object();
                avm1Context.globals.asSetPublicProperty('_root', as2Object);
                avm1Context.globals.asSetPublicProperty('_level0', as2Object);
                avm1Context.globals.asSetPublicProperty('_level1', as2Object);
                var parameters = loader.loaderInfo._parameters;
                for (var paramName in parameters) {
                  if (!(paramName in as2Object)) {
                    as2Object[paramName] = parameters[paramName];
                  }
                }
              }
              var isRootMovie = parent && parent == loader._stage && loader._stage._children.length === 0;
              if (isRootMovie) {
                parent._frameRate = loaderInfo._frameRate;
                parent._stageHeight = loaderInfo._height;
                parent._stageWidth = loaderInfo._width;
                parent._root = root;
                parent._setup();
              } else {
                loader._children.push(root);
              }
              var labels;
              labelMap = root.symbol.labelMap = createEmptyObject();
              if (sceneData) {
                var scenes = [];
                var startFrame;
                var endFrame = root.symbol.totalFrames - 1;
                var sd = sceneData.scenes;
                var ld = sceneData.labels;
                var i = sd.length;
                while (i--) {
                  var s = sd[i];
                  startFrame = s.offset;
                  labels = [];
                  var j = ld.length;
                  while (j--) {
                    var lbl = ld[j];
                    if (lbl.frame >= startFrame && lbl.frame <= endFrame) {
                      labelMap[lbl.name] = lbl.frame + 1;
                      labels.unshift(new flash.display.FrameLabel(lbl.name, lbl.frame - startFrame + 1));
                    }
                  }
                  var scene = new flash.display.Scene(s.name, labels, endFrame - startFrame + 1);
                  scene._startFrame = startFrame + 1;
                  scene._endFrame = endFrame + 1;
                  scenes.unshift(scene);
                  endFrame = startFrame - 1;
                }
                root.symbol.scenes = scenes;
              } else {
                labels = [];
                if (labelName) {
                  labelMap[labelName] = frameNum;
                  labels.push(new flash.display.FrameLabel(labelName, frameNum));
                }
                var scene = new flash.display.Scene('Scene 1', labels, root.symbol.totalFrames);
                scene._startFrame = 1;
                scene._endFrame = root.symbol.totalFrames;
                root.symbol.scenes = [
                  scene
                ];
              }
              if (loader._stage) {
                loader._stage._children[0] = root;
              }
              rootClass.instanceConstructor.call(root);
              loader._content = root;
            } else {
              root._framesLoaded = framesLoaded;
              if (labelName && root._labelMap) {
                if (root._labelMap[labelName] === undefined) {
                  root._labelMap[labelName] = frameNum;
                  for (var i = 0, n = root.symbol.scenes.length; i < n; i++) {
                    var scene = root.symbol.scenes[i];
                    if (frameNum >= scene._startFrame && frameNum <= scene._endFrame) {
                      scene.labels.push(new flash.display.FrameLabel(labelName, frameNum - scene._startFrame));
                      break;
                    }
                  }
                }
              }
            }
            if (frame.startSounds) {
              root._registerStartSounds(frameNum, frame.startSounds);
            }
            if (frame.soundStream) {
              root._initSoundStream(frame.soundStream);
            }
            if (frame.soundStreamBlock) {
              root._addSoundStreamBlock(frameNum, frame.soundStreamBlock);
            }
            if (!loader._isAvm2Enabled) {
              var avm1Context = loader._avm1Context;
              if (initActionBlocks) {
                for (var i = 0; i < initActionBlocks.length; i++) {
                  var spriteId = initActionBlocks[i].spriteId;
                  var actionsData = initActionBlocks[i].actionsData;
                  root.addFrameScript(frameNum - 1, function (actionsData, spriteId, state) {
                    if (state.executed)
                      return;
                    state.executed = true;
                    return executeActions(actionsData, avm1Context, this._getAS2Object());
                  }.bind(root, actionsData, spriteId, {
                    executed: false
                  }));
                }
              }
              if (actionBlocks) {
                for (var i = 0; i < actionBlocks.length; i++) {
                  var block = actionBlocks[i];
                  root.addFrameScript(frameNum - 1, function (block) {
                    return function () {
                      return executeActions(block, avm1Context, this._getAS2Object());
                    };
                  }(block));
                }
              }
            }
            if (frameNum === 1)
              loaderInfo._dispatchEvent(new flash.events.Event('init', false, false));
            framePromiseResolve(frame);
          });
        },
        _commitImage: function (imageInfo) {
          var loader = this;
          var imgPromiseResolve;
          var imgPromise = this._lastPromise = new Promise(function (resolve) {
              imgPromiseResolve = resolve;
            });
          var img = new Image();
          imageInfo.props.img = img;
          img.onload = function () {
            var Bitmap = avm2.systemDomain.getClass('flash.display.Bitmap');
            var BitmapData = avm2.systemDomain.getClass('flash.display.BitmapData');
            var props = imageInfo.props;
            props.parent = loader._parent;
            props.stage = loader._stage;
            props.skipCopyToCanvas = true;
            var bitmapData = BitmapData.createAsSymbol(props);
            BitmapData.instanceConstructor.call(bitmapData, 0, 0, true, 4294967295);
            var image = Bitmap.createAsSymbol(bitmapData);
            Bitmap.instanceConstructor.call(image, bitmapData);
            image._parent = loader;
            loader._children.push(image);
            loader._invalidateBounds();
            loader._content = image;
            imgPromiseResolve(imageInfo);
            var loaderInfo = loader._contentLoaderInfo;
            loaderInfo._width = image.width;
            loaderInfo._height = image.height;
            loaderInfo._dispatchEvent('init');
          };
          img.src = URL.createObjectURL(imageInfo.data);
          imageInfo.data = null;
        },
        _commitSymbol: function (symbol) {
          var dictionary = this._dictionary;
          var dictionaryResolved = this._dictionaryResolved;
          if ('updates' in symbol) {
            dictionary[symbol.id].then(function (s) {
              for (var i in symbol.updates) {
                s.props[i] = symbol.updates[i];
              }
            });
            return;
          }
          var className = 'flash.display.DisplayObject';
          var dependencies = symbol.require;
          var promiseQueue = [];
          var props = {
              symbolId: symbol.id,
              loader: this
            };
          var symbolPromiseResolve;
          var symbolPromise = new Promise(function (resolve) {
              symbolPromiseResolve = resolve;
            });
          if (dependencies && dependencies.length) {
            for (var i = 0, n = dependencies.length; i < n; i++) {
              var dependencyId = dependencies[i];
              var dependencyPromise = dictionary[dependencyId];
              if (dependencyPromise && !dictionaryResolved[dependencyId])
                promiseQueue.push(dependencyPromise);
            }
          }
          switch (symbol.type) {
          case 'button':
            var states = {};
            for (var stateName in symbol.states) {
              var characters = [];
              var displayList = {};
              var state = symbol.states[stateName];
              var depths = Object.keys(state);
              for (var i = 0; i < depths.length; i++) {
                var depth = depths[i];
                var cmd = state[depth];
                var characterPromise = dictionary[cmd.symbolId];
                if (characterPromise && !dictionaryResolved[cmd.symbolId]) {
                  promiseQueue.push(characterPromise);
                }
                characters.push(characterPromise);
                displayList[depth] = Object.create(cmd, {
                  symbolInfo: {
                    get: function (dictionaryResolved, symbolId) {
                      return function () {
                        return dictionaryResolved[symbolId];
                      };
                    }(dictionaryResolved, cmd.symbolId)
                  }
                });
              }
              depths.sort(sortNumeric);
              displayList.depths = depths;
              states[stateName] = {
                className: 'flash.display.Sprite',
                props: {
                  loader: this,
                  timeline: [
                    displayList
                  ]
                }
              };
            }
            className = 'flash.display.SimpleButton';
            props.states = states;
            props.buttonActions = symbol.buttonActions;
            break;
          case 'font':
            var charset = fromCharCode.apply(null, symbol.codes);
            if (charset) {
              style.insertRule('@font-face{font-family:"' + symbol.uniqueName + '";' + 'src:url(data:font/opentype;base64,' + btoa(symbol.data) + ')' + '}', style.cssRules.length);
              if (!/Mozilla\/5.0.*?rv:(\d+).*? Gecko/.test(window.navigator.userAgent)) {
                var testDiv = document.createElement('div');
                testDiv.setAttribute('style', 'position: absolute; top: 0; right: 0;visibility: hidden; z-index: -500;font-family:"' + symbol.uniqueName + '";');
                testDiv.textContent = 'font test';
                document.body.appendChild(testDiv);
                var fontPromise = new Promise(function (resolve) {
                    setTimeout(function () {
                      resolve();
                      document.body.removeChild(testDiv);
                    }, 200);
                  });
                promiseQueue.push(fontPromise);
              }
            }
            className = 'flash.text.Font';
            props.name = symbol.name;
            props.uniqueName = symbol.uniqueName;
            props.charset = symbol.charset;
            props.bold = symbol.bold;
            props.italic = symbol.italic;
            props.metrics = symbol.metrics;
            this._registerFont(className, props);
            break;
          case 'image':
            var img = new Image();
            var imgPromiseResolve;
            var imgPromise = new Promise(function (resolve) {
                imgPromiseResolve = resolve;
              });
            img.onload = function () {
              if (symbol.mask) {
                var maskCanvas = document.createElement('canvas');
                maskCanvas.width = symbol.width;
                maskCanvas.height = symbol.height;
                var maskContext = maskCanvas.getContext('2d');
                maskContext.drawImage(img, 0, 0);
                var maskImageData = maskContext.getImageData(0, 0, symbol.width, symbol.height);
                var maskImageDataBytes = maskImageData.data;
                var symbolMaskBytes = symbol.mask;
                var length = maskImageData.width * maskImageData.height;
                for (var i = 0, j = 3; i < length; i++, j += 4) {
                  maskImageDataBytes[j] = symbolMaskBytes[i];
                }
                maskContext.putImageData(maskImageData, 0, 0);
                props.img = maskCanvas;
              }
              imgPromiseResolve();
            };
            img.src = URL.createObjectURL(symbol.data);
            promiseQueue.push(imgPromise);
            className = 'flash.display.Bitmap';
            props.img = img;
            props.width = symbol.width;
            props.height = symbol.height;
            break;
          case 'label':
            var drawFn = new Function('c,r,ct', symbol.data);
            className = 'flash.text.StaticText';
            props.bbox = symbol.bbox;
            props.draw = drawFn;
            break;
          case 'text':
            props.bbox = symbol.bbox;
            props.html = symbol.html;
            if (symbol.type === 'label') {
              className = 'flash.text.StaticText';
            } else {
              className = 'flash.text.TextField';
              props.tag = symbol.tag;
              props.variableName = symbol.variableName;
            }
            break;
          case 'shape':
            className = symbol.morph ? 'flash.display.MorphShape' : 'flash.display.Shape';
            props.bbox = symbol.bbox;
            props.strokeBbox = symbol.strokeBbox;
            props.paths = symbol.paths;
            props.dictionaryResolved = dictionaryResolved;
            break;
          case 'sound':
            if (!symbol.pcm && !PLAY_USING_AUDIO_TAG) {
              var decodePromiseResolve;
              var decodePromise = new Promise(function (resolve) {
                  decodePromiseResolve = resolve;
                });
              MP3DecoderSession.processAll(symbol.packaged.data, function (props, pcm, id3tags, error) {
                props.pcm = pcm || new Uint8Array(0);
                decodePromiseResolve();
                if (error) {
                  console.error('ERROR: ' + error);
                }
              }.bind(null, props));
              promiseQueue.push(decodePromise);
            }
            className = 'flash.media.Sound';
            props.sampleRate = symbol.sampleRate;
            props.channels = symbol.channels;
            props.pcm = symbol.pcm;
            props.packaged = symbol.packaged;
            break;
          case 'binary':
            props.data = symbol.data;
            break;
          case 'sprite':
            var displayList = null;
            var frameCount = symbol.frameCount;
            var labelMap = {};
            var frameNum = 1;
            var frames = symbol.frames;
            var timeline = [];
            var startSoundRegistrations = [];
            for (var i = 0, n = frames.length; i < n; i++) {
              var frame = frames[i];
              var frameNum = timeline.length + 1;
              if (frame.labelName) {
                labelMap[frame.labelName] = frameNum;
              }
              if (frame.startSounds) {
                startSoundRegistrations[frameNum] = frame.startSounds;
                for (var j = 0; j < frame.startSounds.length; j++) {
                  var soundId = frame.startSounds[j].soundId;
                  var itemPromise = dictionary[soundId];
                  if (itemPromise && !dictionaryResolved[soundId]) {
                    promiseQueue.push(itemPromise);
                  }
                }
              }
              displayList = this._buildFrame(displayList, timeline, promiseQueue, frame, frameNum);
            }
            var frameScripts = {};
            if (!this._isAvm2Enabled) {
              if (symbol.frameScripts) {
                var data = symbol.frameScripts;
                for (var i = 0; i < data.length; i += 2) {
                  var frameNum = data[i] + 1;
                  var block = data[i + 1];
                  var script = function (block, loader) {
                      return function () {
                        var avm1Context = loader._avm1Context;
                        return executeActions(block, avm1Context, this._getAS2Object());
                      };
                    }(block, this);
                  if (!frameScripts[frameNum])
                    frameScripts[frameNum] = [
                      script
                    ];
                  else
                    frameScripts[frameNum].push(script);
                }
              }
            }
            className = 'flash.display.MovieClip';
            props.timeline = timeline;
            props.framesLoaded = frameCount;
            props.labelMap = labelMap;
            props.frameScripts = frameScripts;
            props.totalFrames = frameCount;
            props.startSoundRegistrations = startSoundRegistrations;
            break;
          }
          dictionary[symbol.id] = symbolPromise;
          Promise.all(promiseQueue).then(function () {
            var symbolInfo = {
                className: className,
                props: props
              };
            dictionaryResolved[symbol.id] = symbolInfo;
            symbolPromiseResolve(symbolInfo);
          });
        },
        _registerFont: function (className, props) {
          this._vmPromise.then(function () {
            var fontClass = avm2.applicationDomain.getClass(className);
            var font = fontClass.createAsSymbol(props);
            fontClass.instanceConstructor.call(font);
          });
        },
        _init: function (info) {
          var loader = this;
          var loaderInfo = loader._contentLoaderInfo;
          loaderInfo._swfVersion = info.swfVersion;
          var bbox = info.bbox;
          loaderInfo._width = bbox.xMax - bbox.xMin;
          loaderInfo._height = bbox.yMax - bbox.yMin;
          loaderInfo._frameRate = info.frameRate;
          var vmPromiseResolve, vmPromiseReject;
          var vmPromise = new Promise(function (resolve, reject) {
              vmPromiseResolve = resolve;
              vmPromiseReject = reject;
            });
          vmPromise.resolve = vmPromiseResolve;
          vmPromise.reject = vmPromiseReject;
          var documentPromise = new Promise(function (resolve) {
              vmPromise.then(function () {
                var rootInfo = {
                    className: 'flash.display.MovieClip',
                    props: {
                      totalFrames: info.frameCount
                    }
                  };
                loader._dictionaryResolved[0] = rootInfo;
                resolve(rootInfo);
              });
            });
          loader._dictionary[0] = documentPromise;
          loader._lastPromise = documentPromise;
          loader._vmPromise = vmPromise;
          loader._isAvm2Enabled = info.fileAttributes.doAbc;
          this._setup();
        },
        _load: function (request, checkPolicyFile, applicationDomain, securityDomain, requestedContentParent, parameters, deblockingFilter, allowCodeImport, imageDecodingPolicy) {
          if (flash.net.URLRequest.class.isInstanceOf(request)) {
            this._contentLoaderInfo._url = request._url;
          }
          var worker;
          if (WORKERS_ENABLED) {
            worker = new Worker(SHUMWAY_ROOT + LOADER_PATH);
          } else {
            worker = new ResourceLoader(window);
          }
          var loader = this;
          loader._worker = worker;
          worker.onmessage = function (evt) {
            if (evt.data.type === 'exception') {
              avm2.exceptions.push({
                source: 'parser',
                message: evt.data.message,
                stack: evt.data.stack
              });
            } else {
              loader._commitData(evt.data);
            }
          };
          if (flash.net.URLRequest.class.isInstanceOf(request)) {
            var session = FileLoadingService.createSession();
            session.onprogress = function (data, progress) {
              worker.postMessage({
                data: data,
                progress: progress
              });
            };
            session.onerror = function (error) {
              loader._commitData({
                command: 'error',
                error: error
              });
            };
            session.onopen = function () {
              worker.postMessage('pipe:');
            };
            session.onclose = function () {
              worker.postMessage({
                data: null
              });
            };
            session.open(request._toFileRequest());
          } else {
            worker.postMessage(request);
          }
        },
        _setup: function () {
          var loader = this;
          var stage = loader._stage;
          if (loader._isAvm2Enabled) {
            var mouseClass = avm2.systemDomain.getClass('flash.ui.Mouse');
            mouseClass._stage = stage;
            loader._vmPromise.resolve();
            return;
          }
          if (!avm2.loadAVM1) {
            loader._vmPromise.reject('AVM1 loader is not found');
            return;
          }
          var loaded = function () {
            var loaderInfo = loader._contentLoaderInfo;
            var avm1Context = new AS2Context(loaderInfo._swfVersion);
            avm1Context.stage = stage;
            loader._avm1Context = avm1Context;
            avm1lib.AS2Key.class.$bind(stage);
            avm1lib.AS2Mouse.class.$bind(stage);
            stage._addEventListener('frameConstructed', avm1Context.flushPendingScripts.bind(avm1Context), false, Number.MAX_VALUE);
            loader._vmPromise.resolve();
          };
          if (avm2.isAVM1Loaded) {
            if (AS2Context.instance) {
              loader._avm1Context = AS2Context.instance;
              loader._vmPromise.resolve();
            } else {
              loaded();
            }
          } else {
            avm2.isAVM1Loaded = true;
            avm2.loadAVM1(loaded);
          }
        },
        get contentLoaderInfo() {
          return this._contentLoaderInfo;
        },
        get content() {
          somewhatImplemented('Loader.content');
          return this._content;
        }
      };
    def.__glue__ = {
      native: {
        instance: {
          content: Object.getOwnPropertyDescriptor(def, 'content'),
          contentLoaderInfo: Object.getOwnPropertyDescriptor(def, 'contentLoaderInfo'),
          _getJPEGLoaderContextdeblockingfilter: function (context) {
            return 0;
          },
          _load: def._load,
          _loadBytes: function _loadBytes(bytes, checkPolicyFile, applicationDomain, securityDomain, requestedContentParent, parameters, deblockingFilter, allowLoadBytesCodeExecution, imageDecodingPolicy) {
            this._load(bytes.a, checkPolicyFile, applicationDomain, securityDomain, requestedContentParent, parameters, deblockingFilter, allowLoadBytesCodeExecution, imageDecodingPolicy);
          },
          _unload: function _unload(halt, gc) {
            somewhatImplemented('Loader._unload, do we even need to do anything here?');
          },
          _close: function _close() {
            somewhatImplemented('Loader._close');
          },
          _getUncaughtErrorEvents: function _getUncaughtErrorEvents() {
            somewhatImplemented('Loader._getUncaughtErrorEvents');
            return this._uncaughtErrorEvents;
          },
          _setUncaughtErrorEvents: function _setUncaughtErrorEvents(value) {
            somewhatImplemented('Loader._setUncaughtErrorEvents');
            this._uncaughtErrorEvents = value;
          }
        }
      }
    };
    return def;
  }.call(this);
var LoaderInfoDefinition = function () {
    function dispatchEvent(event) {
      notImplemented('LoaderInfo.dispatchEvent');
    }
    return {
      __class__: 'flash.display.LoaderInfo',
      initialize: function () {
        this._actionScriptVersion = null;
        this._backgroundColor = null;
        this._bytes = null;
        this._bytesLoaded = 0;
        this._bytesTotal = 0;
        this._content = null;
        this._contentType = null;
        this._frameRate = null;
        this._height = null;
        this._loader = null;
        this._loaderURL = null;
        this._swfVersion = null;
        this._url = null;
        this._width = null;
        this._uncaughtErrorEvents = null;
      },
      __glue__: {
        native: {
          static: {
            getLoaderInfoByDefinition: function getLoaderInfoByDefinition(object) {
              notImplemented('LoaderInfo.getLoaderInfoByDefinition');
            }
          },
          instance: {
            _getArgs: function _getArgs() {
              var params = this._parameters;
              var mangled = {};
              for (var k in params) {
                mangled[Multiname.getPublicQualifiedName(k)] = params[k];
              }
              return mangled;
            },
            _getUncaughtErrorEvents: function _getUncaughtErrorEvents() {
              somewhatImplemented('Loader._getUncaughtErrorEvents');
              return this._uncaughtErrorEvents;
            },
            _setUncaughtErrorEvents: function _setUncaughtErrorEvents(value) {
              somewhatImplemented('Loader._setUncaughtErrorEvents');
              this._uncaughtErrorEvents = value;
            },
            loaderURL: {
              get: function loaderURL() {
                return this._loaderURL;
              }
            },
            url: {
              get: function url() {
                return this._url;
              }
            },
            isURLInaccessible: {
              get: function isURLInaccessible() {
                return this._isURLInaccessible;
              }
            },
            bytesLoaded: {
              get: function bytesLoaded() {
                return this._bytesLoaded;
              }
            },
            bytesTotal: {
              get: function bytesTotal() {
                return this._bytesTotal;
              }
            },
            applicationDomain: {
              get: function applicationDomain() {
                return new flash.system.ApplicationDomain(avm2.applicationDomain);
              }
            },
            swfVersion: {
              get: function swfVersion() {
                return this._swfVersion;
              }
            },
            actionScriptVersion: {
              get: function actionScriptVersion() {
                return this._actionScriptVersion;
              }
            },
            frameRate: {
              get: function frameRate() {
                return this._frameRate;
              }
            },
            width: {
              get: function width() {
                return this._width;
              }
            },
            height: {
              get: function height() {
                return this._height;
              }
            },
            contentType: {
              get: function contentType() {
                return this._contentType;
              }
            },
            sharedEvents: {
              get: function sharedEvents() {
                return this._sharedEvents;
              }
            },
            parentSandboxBridge: {
              get: function parentSandboxBridge() {
                return this._parentSandboxBridge;
              },
              set: function parentSandboxBridge(door) {
                this._parentSandboxBridge = door;
              }
            },
            childSandboxBridge: {
              get: function childSandboxBridge() {
                return this._childSandboxBridge;
              },
              set: function childSandboxBridge(door) {
                this._childSandboxBridge = door;
              }
            },
            sameDomain: {
              get: function sameDomain() {
                return this._sameDomain;
              }
            },
            childAllowsParent: {
              get: function childAllowsParent() {
                return this._childAllowsParent;
              }
            },
            parentAllowsChild: {
              get: function parentAllowsChild() {
                return this._parentAllowsChild;
              }
            },
            loader: {
              get: function loader() {
                return this._loader;
              }
            },
            content: {
              get: function content() {
                return this._loader._content;
              }
            },
            bytes: {
              get: function bytes() {
                return this._bytes;
              }
            }
          }
        },
        script: {
          instance: scriptProperties('public', [
            'swfVersion',
            'bytesTotal',
            'bytesLoaded',
            'parameters',
            'uncaughtErrorEvent'
          ])
        }
      }
    };
  }.call(this);
var MorphShapeDefinition = function () {
    var def = {
        __class__: 'flash.display.MorphShape',
        initialize: function () {
          var graphics = this._graphics = new flash.display.Graphics();
          var s = this.symbol;
          if (s && s.paths) {
            graphics._paths = s.paths;
            graphics.bbox = s.bbox;
            graphics.strokeBbox = s.strokeBbox;
            if (this._stage && this._stage._quality === 'low' && !graphics._bitmap)
              graphics._cacheAsBitmap(this._bbox);
          }
        }
      };
    def.__glue__ = {
      native: {
        instance: {
          graphics: {
            get: function () {
              return this._graphics;
            }
          }
        }
      }
    };
    return def;
  }.call(this);
var MovieClipDefinition = function () {
    var def = {
        __class__: 'flash.display.MovieClip',
        initialize: function () {
          this._playHead = 1;
          this._currentFrame = 1;
          this._currentFrameLabel = null;
          this._currentLabel = null;
          this._currentScene = 0;
          this._enabled = true;
          this._frameScripts = {};
          this._framesLoaded = 1;
          this._isPlaying = false;
          this._labelMap = {};
          this._sceneFrameMap = {};
          this._sceneMap = {};
          this._scenes = null;
          this._timeline = null;
          this._totalFrames = 1;
          this._startSoundRegistrations = [];
          this._allowFrameNavigation = true;
          this._complete = true;
          var s = this.symbol;
          if (s) {
            this._timeline = s.timeline || null;
            this._framesLoaded = s.framesLoaded || 1;
            this._labelMap = Object.create(s.labelMap || null);
            this._frameScripts = Object.create(s.frameScripts || null);
            this._totalFrames = s.totalFrames || 1;
            this._startSoundRegistrations = s.startSoundRegistrations || [];
            this._scenes = s.scenes || null;
            this._complete = s.complete === false ? false : true;
            var map = this._labelMap;
            for (var name in map) {
              var frame = map[name];
              if (frame == 1) {
                this._currentFrameLabel = this._currentLabel = name;
              }
            }
          }
          this._enterFrame(1);
          var self = this;
          this._onExecuteFrame = function onExecuteFrame() {
            self._removeEventListener('executeFrame', onExecuteFrame);
            self._allowFrameNavigation = false;
            self._callFrame(self._currentFrame);
            self._allowFrameNavigation = true;
            if (self._playHead !== self._currentFrame) {
              self._gotoFrame(self._playHead, true);
            }
            self._postConstructChildren();
          };
          this._addEventListener('executeFrame', this._onExecuteFrame);
          if (this._complete && this._totalFrames <= 1) {
            return this;
          }
          this._onAdvanceFrame = function onAdvanceFrame() {
            var frameNum = self._playHead + 1;
            if (self._complete && frameNum > self._totalFrames) {
              frameNum = 1;
            } else if (frameNum > self._framesLoaded) {
              return;
            }
            self._updateDisplayList(frameNum);
            if (self._sparse) {
              self._addEventListener('constructChildren', self._onConstructChildren);
            }
            self._startSounds(frameNum);
            self._enterFrame(frameNum);
            if (frameNum in self._frameScripts) {
              self._addEventListener('executeFrame', self._onExecuteFrame);
            }
          };
          this._onConstructChildren = function onConstructChildren() {
            self._removeEventListener('constructChildren', onConstructChildren);
            self._constructChildren();
          };
          this.play();
        },
        _updateDisplayList: function (nextFrameNum) {
          this._destructChildren(nextFrameNum);
          this._declareChildren(nextFrameNum);
        },
        _declareChildren: function declareChildren(nextFrameNum) {
          var currentFrame = this._currentFrame;
          if (nextFrameNum === currentFrame) {
            return;
          }
          var timeline = this._timeline;
          var nextDisplayList = timeline[nextFrameNum - 1];
          if (nextDisplayList === timeline[currentFrame - 1]) {
            return;
          }
          var prevDisplayListItem = null;
          var currentDisplayListItem = this._currentDisplayList;
          var children = this._children;
          var depths = nextDisplayList.depths;
          var index = children.length;
          var i = depths.length;
          while (i--) {
            var depth = depths[i], depthInt = depth | 0;
            while (currentDisplayListItem && currentDisplayListItem.depth > depthInt) {
              prevDisplayListItem = currentDisplayListItem;
              currentDisplayListItem = currentDisplayListItem.next;
            }
            var currentChild = null;
            if (currentDisplayListItem && currentDisplayListItem.depth === depthInt) {
              currentChild = currentDisplayListItem.obj;
              if (currentChild && currentChild._owned) {
                index = this.getChildIndex(currentChild);
              }
            }
            var currentCmd = currentDisplayListItem && currentDisplayListItem.depth === depthInt ? currentDisplayListItem.cmd : null;
            var nextCmd = nextDisplayList[depth];
            if (!nextCmd || nextCmd === currentCmd) {
              continue;
            }
            if (currentCmd && currentChild && nextCmd.symbolId === currentCmd.symbolId && nextCmd.ratio === currentCmd.ratio) {
              if (currentChild._animated) {
                currentChild._invalidate();
                if (nextCmd.hasMatrix) {
                  currentChild._setTransformMatrix(nextCmd.matrix, false);
                }
                if (nextCmd.hasCxform) {
                  currentChild._cxform = nextCmd.cxform;
                }
                if (nextCmd.clip) {
                  currentChild._clipDepth = nextCmd.clipDepth;
                }
                if (nextCmd.hasName) {
                  currentChild.name = nextCmd.name;
                }
                if (nextCmd.blend) {
                  currentChild._blendMode = this._resolveBlendMode(nextCmd.blendMode);
                }
              }
              currentDisplayListItem.cmd = nextCmd;
              continue;
            }
            var newDisplayListItem = this._addTimelineChild(nextCmd, index);
            newDisplayListItem.next = currentDisplayListItem;
            if (prevDisplayListItem) {
              prevDisplayListItem.next = newDisplayListItem;
            } else {
              this._currentDisplayList = newDisplayListItem;
            }
            prevDisplayListItem = newDisplayListItem;
          }
        },
        _destructChildren: function destructChildren(nextFrameNum) {
          var currentFrame = this._currentFrame;
          if (nextFrameNum === currentFrame) {
            return;
          }
          var timeline = this._timeline;
          var nextDisplayList = timeline[nextFrameNum - 1];
          if (nextDisplayList === timeline[currentFrame - 1]) {
            return;
          }
          var prevEntry = null;
          var currentEntry = this._currentDisplayList;
          var toRemove = null;
          while (currentEntry) {
            var depth = currentEntry.depth;
            var currentCmd = currentEntry.cmd;
            var nextCmd = nextDisplayList[depth];
            if (!nextCmd || nextCmd.symbolId !== currentCmd.symbolId || nextCmd.ratio !== currentCmd.ratio) {
              var nextDisplayListItem = currentEntry.next;
              if (prevEntry) {
                prevEntry.next = nextDisplayListItem;
              } else {
                this._currentDisplayList = nextDisplayListItem;
              }
              currentEntry.next = toRemove;
              toRemove = currentEntry;
              currentEntry = nextDisplayListItem;
            } else {
              prevEntry = currentEntry;
              currentEntry = currentEntry.next;
            }
          }
          while (toRemove) {
            var child = toRemove.obj;
            if (child && child._owned) {
              this._sparse = true;
              this.removeChild(child);
              child.destroy();
              if (child._isPlaying) {
                child.stop();
              }
            }
            toRemove = toRemove.next;
          }
        },
        _gotoFrame: function gotoFrame(frameNum, execute) {
          var enterFrame = frameNum !== this._currentFrame;
          if (this._allowFrameNavigation || !this._loader._isAvm2Enabled) {
            if (enterFrame) {
              this._updateDisplayList(frameNum);
              this._enterFrame(frameNum);
            }
            this._constructChildren();
            if (this._loader._isAvm2Enabled && this.loaderInfo._swfVersion >= 10) {
              if (enterFrame) {
                this._addEventListener('executeFrame', this._onExecuteFrame);
              }
              var domain = avm2.systemDomain;
              domain.broadcastMessage('frameConstructed');
              domain.broadcastMessage('executeFrame');
              domain.broadcastMessage('exitFrame');
              return;
            }
            if (enterFrame && (execute || !this._loader._isAvm2Enabled)) {
              this._callFrame(frameNum);
            }
            this._postConstructChildren();
            return;
          }
          if (enterFrame) {
            this._playHead = frameNum;
          }
        },
        _enterFrame: function navigate(frameNum) {
          if (frameNum === this._currentFrame) {
            return;
          }
          this._currentFrameLabel = null;
          if (frameNum === 1) {
            this._currentLabel = null;
          }
          var map = this._labelMap;
          for (var name in map) {
            if (map[name] === frameNum) {
              this._currentFrameLabel = this._currentLabel = name;
              break;
            }
          }
          if (this._scenes) {
            var scenes = this._scenes;
            for (var j = 0, n = scenes.length; j < n; j++) {
              var scene = scenes[j];
              if (frameNum >= scene._startFrame && frameNum <= scene._endFrame) {
                this._currentScene = j;
                break;
              }
            }
          }
          this._playHead = this._currentFrame = frameNum;
        },
        _callFrame: function callFrame(frame) {
          if (isNaN(frame)) {
            frame = this._labelMap[frame];
            if (frame === undefined) {
              return;
            }
          }
          if (frame in this._frameScripts) {
            var scripts = this._frameScripts[frame];
            try {
              for (var i = 0, n = scripts.length; i < n; i++) {
                scripts[i].call(this);
              }
            } catch (e) {
              var AVM2_ERROR_TYPE = 2;
              TelemetryService.reportTelemetry({
                topic: 'error',
                error: AVM2_ERROR_TYPE
              });
              if (false) {
                console.error('error ' + e + ', stack: \n' + e.stack);
              }
              this.stop();
              throw e;
            }
          }
        },
        _gotoButtonState: function gotoButtonState(stateName) {
          if (this._enabled) {
            this.gotoLabel('_' + stateName);
          }
        },
        _getAbsFrameNum: function (frameNum, sceneName) {
          if (frameNum < 1) {
            frameNum = 1;
          }
          if (sceneName && this._scenes && this._scenes.length > 1) {
            var scenes = this._scenes;
            for (var i = 0; i < scenes.length; i++) {
              var scene = scenes[i];
              if (scene.name === sceneName) {
                frameNum += scene._startFrame - 1;
                if (frameNum > scene._endFrame) {
                  frameNum = scene._endFrame;
                }
                break;
              }
            }
          }
          if (frameNum > this._framesLoaded) {
            return this._framesLoaded;
          }
          return frameNum;
        },
        _registerStartSounds: function (frameNum, starts) {
          this._startSoundRegistrations[frameNum] = starts;
        },
        _initSoundStream: function (streamInfo) {
          this._soundStream = new MovieClipSoundStream(streamInfo, this);
        },
        _addSoundStreamBlock: function (frameNum, streamBlock) {
          this._soundStream.appendBlock(frameNum, streamBlock);
        },
        _startSounds: function (frameNum) {
          var starts = this._startSoundRegistrations[frameNum];
          if (starts) {
            var sounds = this._sounds || (this._sounds = {});
            var loader = this.loaderInfo._loader;
            for (var i = 0; i < starts.length; i++) {
              var start = starts[i];
              var symbolId = start.soundId;
              var info = start.soundInfo;
              var sound = sounds[symbolId];
              if (!sound) {
                var symbolInfo = loader._dictionaryResolved[symbolId];
                if (!symbolInfo)
                  continue;
                var symbolClass = avm2.systemDomain.findClass(symbolInfo.className) ? avm2.systemDomain.getClass(symbolInfo.className) : avm2.applicationDomain.getClass(symbolInfo.className);
                var soundObj = symbolClass.createAsSymbol(symbolInfo.props);
                symbolClass.instanceConstructor.call(soundObj);
                sounds[symbolId] = sound = {
                  object: soundObj
                };
              }
              if (sound.channel) {
                sound.channel.stop();
                sound.channel = null;
              }
              if (!info.stop) {
                var loops = info.hasLoops ? info.loopCount : 0;
                sound.channel = sound.object.play(0, loops);
              }
            }
          }
          if (this._soundStream) {
            this._soundStream.playFrame(frameNum);
          }
        },
        _getAS2Object: function () {
          if (!this.$as2Object) {
            if (this._avm1SymbolClass) {
              var nativeObject = this, nativeObjectClass = this._avm1SymbolClass;
              var constructWrapper = function () {
                this.init(nativeObject);
                nativeObjectClass.call(this);
              };
              constructWrapper.prototype = Object.create(nativeObjectClass.prototype);
              constructWrapper.instanceConstructor = constructWrapper;
              constructWrapper.debugName = 'avm1 <symbol constructor wrapper>';
              construct(constructWrapper);
            } else {
              new avm1lib.AS2MovieClip(this);
            }
          }
          return this.$as2Object;
        },
        get currentFrame() {
          var frameNum = this._currentFrame;
          return this._scenes ? frameNum - this.currentScene._startFrame + 1 : frameNum;
        },
        get currentFrameLabel() {
          return this._currentFrameLabel;
        },
        get currentLabel() {
          return this._currentLabel;
        },
        get currentLabels() {
          if (this._scenes) {
            return this._scenes[this._currentScene].labels;
          } else {
            var labels = [];
            var map = this._labelMap;
            for (var name in map) {
              labels.push(new flash.display.FrameLabel(name, map[name]));
            }
            return labels;
          }
        },
        get currentScene() {
          return this._scenes ? this._scenes[this._currentScene] : new flash.display.Scene('', this.currentLabels, this._framesLoaded);
        },
        get enabled() {
          return this._enabled;
        },
        set enabled(val) {
          this._enabled = val;
        },
        get framesLoaded() {
          return this._framesLoaded;
        },
        get totalFrames() {
          return this._totalFrames;
        },
        get scenes() {
          return this._scenes || [
            new flash.display.Scene('', this.currentLabels, this._framesLoaded)
          ];
        },
        get trackAsMenu() {
          return false;
        },
        set trackAsMenu(val) {
          notImplemented();
        },
        addFrameScript: function () {
          var frameScripts = this._frameScripts;
          for (var i = 0, n = arguments.length; i < n; i += 2) {
            var frameNum = arguments[i] + 1;
            var fn = arguments[i + 1];
            if (!fn) {
              continue;
            }
            var scripts = frameScripts[frameNum];
            if (scripts) {
              scripts.push(fn);
            } else {
              frameScripts[frameNum] = [
                fn
              ];
            }
            if (frameNum === this._currentFrame) {
              this._addEventListener('executeFrame', this._onExecuteFrame);
            }
          }
        },
        gotoAndPlay: function (frame, scene) {
          this.play();
          if (isNaN(frame)) {
            this.gotoLabel(frame);
          } else {
            this._gotoFrame(this._getAbsFrameNum(frame, scene));
          }
        },
        gotoAndStop: function (frame, scene) {
          this.stop();
          if (isNaN(frame)) {
            this.gotoLabel(frame);
          } else {
            this._gotoFrame(this._getAbsFrameNum(frame, scene));
          }
        },
        gotoLabel: function (labelName) {
          var frameNum = this._labelMap[labelName];
          if (frameNum !== undefined) {
            this._gotoFrame(frameNum);
          }
        },
        isPlaying: function () {
          return this._isPlaying;
        },
        nextFrame: function () {
          this.stop();
          if (this._currentFrame < this._framesLoaded) {
            this._gotoFrame(this._currentFrame + 1);
          }
        },
        nextScene: function () {
          if (this._scenes && this._currentScene < this._scenes.length - 1) {
            this._gotoFrame(this._scenes[this._currentScene + 1]._startFrame);
          }
        },
        play: function () {
          if (this._isPlaying || this._complete && this._totalFrames <= 1) {
            return;
          }
          this._isPlaying = true;
          this._addEventListener('advanceFrame', this._onAdvanceFrame);
        },
        prevFrame: function () {
          this.stop();
          if (this._currentFrame > 1) {
            this._gotoFrame(this._currentFrame - 1);
          }
        },
        prevScene: function () {
          if (this._scenes && this._currentScene > 0) {
            this._gotoFrame(this._scenes[this._currentScene - 1]._startFrame);
          }
        },
        stop: function () {
          if (!this._isPlaying || this._complete && this._totalFrames <= 1) {
            return;
          }
          this._isPlaying = false;
          this._removeEventListener('advanceFrame', this._onAdvanceFrame);
        }
      };
    var desc = Object.getOwnPropertyDescriptor;
    def.__glue__ = {
      native: {
        instance: {
          currentFrame: desc(def, 'currentFrame'),
          framesLoaded: desc(def, 'framesLoaded'),
          totalFrames: desc(def, 'totalFrames'),
          trackAsMenu: desc(def, 'trackAsMenu'),
          scenes: desc(def, 'scenes'),
          currentScene: desc(def, 'currentScene'),
          currentLabel: desc(def, 'currentLabel'),
          currentFrameLabel: desc(def, 'currentFrameLabel'),
          enabled: desc(def, 'enabled'),
          isPlaying: desc(def, 'isPlaying'),
          play: def.play,
          stop: def.stop,
          nextFrame: def.nextFrame,
          prevFrame: def.prevFrame,
          gotoAndPlay: def.gotoAndPlay,
          gotoAndStop: def.gotoAndStop,
          addFrameScript: def.addFrameScript,
          prevScene: def.prevScene,
          nextScene: def.nextScene
        }
      }
    };
    return def;
  }.call(this);
var MovieClipSoundStream = function () {
    var MP3_MIME_TYPE = 'audio/mpeg';
    function openMediaSource(soundStream, mediaSource) {
      var sourceBuffer;
      try {
        sourceBuffer = mediaSource.addSourceBuffer(MP3_MIME_TYPE);
        soundStream.mediaSource = mediaSource;
        soundStream.sourceBuffer = sourceBuffer;
        soundStream.rawFrames.forEach(function (data) {
          sourceBuffer.appendBuffer(data);
        });
        delete soundStream.rawFrames;
      } catch (e) {
        console.error('MediaSource mp3 playback is not supported: ' + e);
      }
    }
    function syncTime(element, movieClip) {
      var initialized = false;
      var startMediaTime, startRealTime;
      element.addEventListener('timeupdate', function (e) {
        if (!initialized) {
          startMediaTime = element.currentTime;
          startRealTime = performance.now();
          initialized = true;
          movieClip._stage._frameScheduler.startTrackDelta();
          return;
        }
        var mediaDelta = element.currentTime - startMediaTime;
        var realDelta = performance.now() - startRealTime;
        movieClip._stage._frameScheduler.setDelta(realDelta - mediaDelta * 1000);
      });
      element.addEventListener('pause', function (e) {
        movieClip._stage._frameScheduler.endTrackDelta();
        initialized = false;
      });
      element.addEventListener('seeking', function (e) {
        movieClip._stage._frameScheduler.endTrackDelta();
        initialized = false;
      });
    }
    function MovieClipSoundStream(streamInfo, movieClip) {
      this.movieClip = movieClip;
      this.data = {
        sampleRate: streamInfo.sampleRate,
        channels: streamInfo.channels
      };
      this.seekIndex = [];
      this.position = 0;
      var isMP3 = streamInfo.format === 'mp3';
      if (isMP3 && PLAY_USING_AUDIO_TAG) {
        var element = document.createElement('audio');
        element.preload = 'metadata';
        element.loop = false;
        syncTime(element, movieClip);
        if (element.canPlayType(MP3_MIME_TYPE)) {
          this.element = element;
          if (typeof MediaSource !== 'undefined') {
            var mediaSource = new MediaSource();
            mediaSource.addEventListener('sourceopen', openMediaSource.bind(null, this, mediaSource));
            element.src = URL.createObjectURL(mediaSource);
          } else {
            console.warn('MediaSource is not supported');
          }
          this.rawFrames = [];
          return;
        }
      }
      var totalSamples = streamInfo.samplesCount * streamInfo.channels;
      this.data.pcm = new Float32Array(totalSamples);
      if (isMP3) {
        var soundStream = this;
        soundStream.decoderPosition = 0;
        soundStream.decoderSession = new MP3DecoderSession();
        soundStream.decoderSession.onframedata = function (frameData) {
          var position = soundStream.decoderPosition;
          soundStream.data.pcm.set(frameData, position);
          soundStream.decoderPosition = position + frameData.length;
        }.bind(this);
        soundStream.decoderSession.onerror = function (error) {
          console.error('ERROR: MP3DecoderSession: ' + error);
        };
      }
    }
    MovieClipSoundStream.prototype = {
      appendBlock: function (frameNum, streamBlock) {
        var streamPosition = this.position;
        this.seekIndex[frameNum] = streamPosition + streamBlock.seek * this.data.channels;
        this.position = streamPosition + streamBlock.samplesCount * this.data.channels;
        if (this.sourceBuffer) {
          this.sourceBuffer.appendBuffer(streamBlock.data);
          return;
        }
        if (this.rawFrames) {
          this.rawFrames.push(streamBlock.data);
          return;
        }
        var decoderSession = this.decoderSession;
        if (decoderSession) {
          decoderSession.pushAsync(streamBlock.data);
        } else {
          this.data.pcm.set(streamBlock.pcm, streamPosition);
        }
      },
      playFrame: function (frameNum) {
        if (isNaN(this.seekIndex[frameNum])) {
          return;
        }
        var PAUSE_WHEN_OF_SYNC_GREATER = 1;
        var PLAYBACK_ADJUSTMENT = 0.25;
        var element = this.element;
        if (element) {
          var soundStreamData = this.data;
          var time = this.seekIndex[frameNum] / soundStreamData.sampleRate / soundStreamData.channels;
          if (!this.channel && (this.movieClip._complete || this.sourceBuffer)) {
            if (!this.sourceBuffer) {
              var blob = new Blob(this.rawFrames);
              element.src = URL.createObjectURL(blob);
            }
            var symbolClass = flash.media.SoundChannel.class;
            var channel = symbolClass.createAsSymbol({
                element: element
              });
            symbolClass.instanceConstructor.call(channel);
            this.channel = channel;
            this.expectedFrame = 0;
            this.waitFor = 0;
          } else if (this.sourceBuffer || !isNaN(element.duration)) {
            if (this.mediaSource && this.movieClip._complete) {
              this.mediaSource.endOfStream();
              this.mediaSource = null;
            }
            var elementTime = element.currentTime;
            if (this.expectedFrame !== frameNum) {
              if (element.paused) {
                element.play();
                element.addEventListener('playing', function setTime(e) {
                  element.removeEventListener('playing', setTime);
                  element.currentTime = time;
                });
              } else {
                element.currentTime = time;
              }
            } else if (this.waitFor > 0) {
              if (this.waitFor <= time) {
                if (element.paused) {
                  element.play();
                }
                this.waitFor = 0;
              }
            } else if (elementTime - time > PAUSE_WHEN_OF_SYNC_GREATER) {
              console.warn('Sound is faster than frames by ' + (elementTime - time));
              this.waitFor = elementTime - PLAYBACK_ADJUSTMENT;
              element.pause();
            } else if (time - elementTime > PAUSE_WHEN_OF_SYNC_GREATER) {
              console.warn('Sound is slower than frames by ' + (time - elementTime));
              element.currentTime = time + PLAYBACK_ADJUSTMENT;
            }
            this.expectedFrame = frameNum + 1;
          }
        } else if (!this.sound) {
          var symbolClass = flash.media.Sound.class;
          var sound = symbolClass.createAsSymbol(this.data);
          symbolClass.instanceConstructor.call(sound);
          var channel = sound.play();
          this.sound = sound;
          this.channel = channel;
        }
      }
    };
    return MovieClipSoundStream;
  }();
var NativeMenuDefinition = function () {
    return {
      __class__: 'flash.display.NativeMenu',
      initialize: function () {
      },
      __glue__: {
        native: {
          static: {},
          instance: {}
        }
      }
    };
  }.call(this);
var NativeMenuItemDefinition = function () {
    return {
      __class__: 'flash.display.NativeMenuItem',
      initialize: function () {
      },
      __glue__: {
        native: {
          static: {},
          instance: {
            enabled: {
              get: function enabled() {
                somewhatImplemented('NativeMenuItem.enabled');
                return this._enabled;
              },
              set: function enabled(isSeparator) {
                somewhatImplemented('NativeMenuItem.enabled');
                this._enabled = isSeparator;
              }
            }
          }
        }
      }
    };
  }.call(this);
var SceneDefinition = function () {
    return {
      __class__: 'flash.display.Scene',
      initialize: function () {
        this._startFrame = 1;
        this._endFrame = 1;
      },
      __glue__: {
        native: {
          static: {},
          instance: {}
        },
        script: {
          static: {},
          instance: {
            name: {
              get: function name() {
                notImplemented('Scene.name');
                return this._name;
              }
            },
            labels: {
              get: function labels() {
                notImplemented('Scene.labels');
                return this._labels;
              }
            },
            numFrames: {
              get: function numFrames() {
                notImplemented('Scene.numFrames');
                return this._numFrames;
              }
            }
          }
        }
      }
    };
  }.call(this);
var ShaderDefinition = function () {
    return {
      __class__: 'flash.display.Shader',
      initialize: function () {
        this._data = null;
      },
      __glue__: {
        native: {
          static: {},
          instance: {
            data: {
              get: function data() {
                return this._data;
              },
              set: function data(p) {
                this._data = p;
              }
            },
            precisionHint: {
              get: function precisionHint() {
                return this._precisionHint;
              },
              set: function precisionHint(p) {
                this._precisionHint = p;
              }
            }
          }
        },
        script: {
          instance: Glue.ALL
        }
      }
    };
  }.call(this);
var ShaderDataDefinition = function () {
    return {
      __class__: 'flash.display.ShaderData',
      initialize: function () {
        this._byteCode = null;
      },
      __glue__: {
        native: {
          static: {},
          instance: {
            _setByteCode: function _setByteCode(code) {
              this._byteCode = code;
            }
          }
        },
        script: {
          instance: Glue.ALL
        }
      }
    };
  }.call(this);
var ShapeDefinition = function () {
    var def = {
        __class__: 'flash.display.Shape',
        initialize: function () {
          var graphics = this._graphics = new flash.display.Graphics();
          graphics._parent = this;
          var s = this.symbol;
          if (s && s.paths) {
            graphics._paths = s.paths;
            for (var i = 0; i < s.paths.length; i++) {
              s.paths[i] = finishShapePath(s.paths[i], s.dictionaryResolved);
            }
            graphics.bbox = s.bbox;
            graphics.strokeBbox = s.strokeBbox;
            if (this._stage && this._stage._quality === 'low' && !graphics._bitmap)
              graphics._cacheAsBitmap(this._bbox);
            this.ratio = s.ratio || 0;
          }
        }
      };
    def.__glue__ = {
      native: {
        instance: {
          graphics: {
            get: function () {
              return this._graphics;
            }
          }
        }
      }
    };
    return def;
  }.call(this);
var SimpleButtonDefinition = function () {
    var AVM1KeyCodeMap = [
        0,
        37,
        39,
        36,
        35,
        45,
        46,
        0,
        8,
        0,
        0,
        0,
        0,
        13,
        38,
        40,
        33,
        34,
        9,
        27
      ];
    var AVM1MouseTransitionEvents = [
        0,
        0,
        1,
        128,
        64,
        0,
        0,
        32,
        2,
        0,
        0,
        4,
        256,
        16,
        8,
        0
      ];
    return {
      __class__: 'flash.display.SimpleButton',
      initialize: function () {
        this._useHandCursor = true;
        this._enabled = true;
        this._trackAsMenu = false;
        this._upState = null;
        this._overState = null;
        this._downState = null;
        this._hitTestState = null;
        this._currentButtonState = 'up';
        this._mouseChildren = false;
        this._buttonMode = true;
        this._prevAvm1StateCode = 0;
        this._avm1StateCode = 0;
        this._avm1MouseEvents = null;
        this._isContainer = true;
        var s = this.symbol;
        if (s) {
          var states = s.states;
          if (states.down) {
            this._downState = this._constructState(states.down, this);
          }
          if (states.hitTest) {
            this._hitTestState = this._constructState(states.hitTest, this);
          }
          if (states.over) {
            this._overState = this._constructState(states.over, this);
          }
          if (states.up) {
            this._upState = this._constructState(states.up, this);
          }
        }
        if (this._loader && !this._loader._isAvm2Enabled && s && s.buttonActions) {
          this._addEventListener('addedToStage', function (e) {
            this._initAvm1Events(s.buttonActions);
          }.bind(this), false);
        }
      },
      _constructState: function constructState(symbolInfo) {
        var symbolClass = avm2.systemDomain.findClass(symbolInfo.className) ? avm2.systemDomain.getClass(symbolInfo.className) : avm2.applicationDomain.getClass(symbolInfo.className);
        var instance = symbolClass.createAsSymbol(symbolInfo.props);
        symbolClass.instanceConstructor.call(instance);
        if (instance._children.length === 1) {
          instance = instance._children[0];
          instance._parent = null;
          instance._index = -1;
        }
        return instance;
      },
      _updateButton: function updateButton() {
        var state = null;
        switch (this._currentButtonState) {
        case 'up':
          state = this._upState;
          break;
        case 'over':
          state = this._overState;
          break;
        case 'down':
          state = this._downState;
          break;
        }
        if (!state) {
          return;
        }
        var currentChild = this._children[0];
        if (currentChild) {
          if (currentChild === state) {
            return;
          }
          if (this._stage) {
            this._stage._removeFromStage(currentChild);
          }
          currentChild._invalidateTransform();
        }
        if (!state) {
          this._children.shift();
          return;
        }
        this._children[0] = state;
        state._parent = this;
        state._invalidateTransform();
        if (this._stage) {
          this._stage._addToStage(state);
        }
      },
      _gotoButtonState: function gotoButtonState(buttonState) {
        this._invalidateBounds();
        this._currentButtonState = buttonState;
        this._updateButton();
        if (this._avm1MouseEvents) {
          this._processAvm1MouseEvents(this._avm1MouseEvents);
        }
      },
      _getRegion: function getRegion(targetCoordSpace) {
        if (!this._hitTestState) {
          return {
            xMin: 0,
            yMin: 0,
            xMax: 0,
            yMax: 0
          };
        }
        var b = this._hitTestState.getBounds(null);
        return this._getTransformedRect(b, targetCoordSpace);
      },
      _getAS2Object: function () {
        if (!this.$as2Object) {
          new avm1lib.AS2Button(this);
        }
        return this.$as2Object;
      },
      _initAvm1Events: function (buttonActions) {
        var loader = this._loader;
        var avm1Context = loader._avm1Context;
        var keyEvents = null;
        for (var i = 0; i < buttonActions.length; i++) {
          var buttonAction = buttonActions[i];
          var fn = function (actionBlock) {
              return executeActions(actionBlock, avm1Context, this._getAS2Object());
            }.bind(this.parent, buttonAction.actionsData);
          var mouseEventFlags = buttonAction.mouseEventFlags;
          if (mouseEventFlags) {
            var mouseEvents = this._avm1MouseEvents || (this._avm1MouseEvents = []);
            mouseEvents.push({
              flags: mouseEventFlags,
              listener: fn
            });
          }
          var keyPress = buttonAction.keyPress;
          if (keyPress) {
            keyEvents = keyEvents || (keyEvents = []);
            keyEvents.push({
              keyCode: AVM1KeyCodeMap[keyPress] || 0,
              charCode: keyPress,
              listener: fn
            });
          }
        }
        if (keyEvents) {
          var keyListener = function (e) {
            for (var i = 0; i < keyEvents.length; i++) {
              var keyEvent = keyEvents[i];
              if (keyEvent.keyCode ? keyEvent.keyCode === e.keyCode : keyEvent.charCode === e.charCode) {
                keyEvent.listener();
              }
            }
          };
          var KeyboardEventClass = flash.events.KeyboardEvent;
          this.stage._addEventListener(KeyboardEventClass.class.KEY_DOWN, keyListener, false);
          this._addEventListener('removedFromStage', function (stage) {
            stage._removeEventListener(KeyboardEventClass.class.KEY_DOWN, keyListener, false);
          }.bind(this, this.stage), false);
        }
      },
      _processAvm1MouseEvents: function (mouseEvents) {
        var prevAvm1StateCode = this._avm1StateCode;
        var avm1StateCode = (this._currentButtonState === 'down' ? 1 : 0) | (this._currentButtonState !== 'up' ? 2 : 0);
        if (prevAvm1StateCode !== avm1StateCode) {
          this._prevAvm1StateCode = prevAvm1StateCode;
          this._avm1StateCode = avm1StateCode;
          var flag = AVM1MouseTransitionEvents[prevAvm1StateCode << 2 | avm1StateCode];
          for (var i = 0; i < mouseEvents.length; i++) {
            var mouseEvent = mouseEvents[i];
            if ((mouseEvent.flags & flag) !== 0) {
              mouseEvent.listener();
            }
          }
        }
      },
      __glue__: {
        native: {
          instance: {
            _updateButton: function _updateButton() {
              this._updateButton();
            },
            useHandCursor: {
              get: function useHandCursor() {
                return this._useHandCursor;
              },
              set: function useHandCursor(value) {
                this._useHandCursor = value;
              }
            },
            enabled: {
              get: function enabled() {
                return this._enabled;
              },
              set: function enabled(value) {
                this._enabled = value;
              }
            },
            trackAsMenu: {
              get: function trackAsMenu() {
                notImplemented('SimpleButton.trackAsMenu');
                return this._trackAsMenu;
              },
              set: function trackAsMenu(value) {
                notImplemented('SimpleButton.trackAsMenu');
                this._trackAsMenu = value;
              }
            },
            upState: {
              get: function upState() {
                return this._upState;
              },
              set: function upState(value) {
                this._upState = value;
                this._updateButton();
              }
            },
            overState: {
              get: function overState() {
                return this._overState;
              },
              set: function overState(value) {
                this._overState = value;
                this._updateButton();
              }
            },
            downState: {
              get: function downState() {
                return this._downState;
              },
              set: function downState(value) {
                this._downState = value;
                this._updateButton();
              }
            },
            hitTestState: {
              get: function hitTestState() {
                return this._hitTestState;
              },
              set: function hitTestState(value) {
                if (value === this._hitTestState) {
                  return;
                }
                this._invalidate();
                this._hitTestState = value;
              }
            },
            soundTransform: {
              get: function soundTransform() {
                notImplemented('SimpleButton.soundTransform');
                return this._soundTransform;
              },
              set: function soundTransform(value) {
                notImplemented('SimpleButton.soundTransform');
                this._soundTransform = value;
              }
            }
          }
        }
      }
    };
  }.call(this);
var SpriteDefinition = function () {
    var def = {
        __class__: 'flash.display.Sprite',
        initialize: function () {
          this._buttonMode = false;
          this._hitArea = null;
          this._useHandCursor = true;
          this._hitTarget = null;
          this._currentDisplayList = null;
          var s = this.symbol;
          if (s) {
            this._graphics = s.graphics || new flash.display.Graphics();
            if (s.timeline) {
              var displayList = s.timeline[0];
              if (displayList) {
                var depths = displayList.depths;
                for (var i = 0; i < depths.length; i++) {
                  var cmd = displayList[depths[i]];
                  if (cmd) {
                    var displayListItem = this._addTimelineChild(cmd);
                    displayListItem.next = this._currentDisplayList;
                    this._currentDisplayList = displayListItem;
                  }
                }
              }
            }
          } else {
            this._graphics = new flash.display.Graphics();
          }
          this._graphics._parent = this;
        },
        _addTimelineChild: function addTimelineChild(cmd, index) {
          var symbolInfo = cmd.symbolInfo;
          var props = Object.create(symbolInfo.props);
          props.symbolId = cmd.symbolId;
          props.depth = cmd.depth;
          if (cmd.clip) {
            props.clipDepth = cmd.clipDepth;
          }
          if (cmd.hasCxform) {
            props.cxform = cmd.cxform;
          }
          if (cmd.hasMatrix) {
            props.currentTransform = cmd.matrix;
          }
          if (cmd.hasName) {
            props.name = cmd.name;
          }
          if (cmd.hasRatio) {
            props.ratio = cmd.ratio / 65535;
          }
          if (cmd.blend) {
            props.blendMode = cmd.blendMode;
          }
          var displayListItem = {
              cmd: cmd,
              depth: cmd.depth,
              className: symbolInfo.className,
              props: props,
              events: cmd.events,
              obj: null
            };
          if (index !== undefined) {
            this._children.splice(index, 0, displayListItem);
          } else {
            this._children.push(displayListItem);
          }
          this._sparse = true;
          return displayListItem;
        },
        _constructChildren: function () {
          if (!this._sparse) {
            return;
          }
          var loader = this._loader;
          var children = this._children;
          for (var i = 0; i < children.length; i++) {
            var displayListItem = children[i];
            Counter.count('constructChild');
            if (flash.display.DisplayObject.class.isInstanceOf(displayListItem)) {
              displayListItem._index = i;
            } else {
              var symbolClass = avm2.systemDomain.findClass(displayListItem.className) ? avm2.systemDomain.getClass(displayListItem.className) : avm2.applicationDomain.getClass(displayListItem.className);
              var props = Object.create(displayListItem.props);
              var name = props.name;
              props.animated = true;
              props.owned = true;
              props.parent = this;
              props.stage = this._stage;
              if (this._level > -1) {
                props.level = this._level + 1;
              }
              props.index = i;
              var instance = symbolClass.createAsSymbol(props);
              if (name) {
                this[Multiname.getPublicQualifiedName(name)] = instance;
              }
              symbolClass.instanceConstructor.call(instance);
              if (flash.display.BitmapData.class.isInstanceOf(instance)) {
                var bitmapData = instance;
                instance = flash.display.Bitmap.class.createAsSymbol(props);
                flash.display.Bitmap.class.instanceConstructor.call(instance, bitmapData);
              }
              if (!loader._isAvm2Enabled) {
                this._initAvm1Bindings(instance, name, displayListItem.events);
                instance._dispatchEvent('init');
                instance._dispatchEvent('construct');
                instance._needLoadEvent = true;
              } else {
                instance._dispatchEvent('load');
              }
              instance._dispatchEvent('added', undefined, true);
              if (this._stage) {
                this._stage._addToStage(instance);
              }
              children[i] = instance;
              displayListItem.obj = instance;
            }
          }
          this._sparse = false;
        },
        _postConstructChildren: function () {
          var loader = this._loader;
          if (!loader || loader._isAvm2Enabled) {
            return;
          }
          var children = this._children;
          for (var i = 0; i < children.length; i++) {
            var instance = children[i];
            if (instance._needLoadEvent) {
              instance._needLoadEvent = false;
              instance._dispatchEvent('load');
            }
          }
        },
        _duplicate: function (name, depth, initObject) {
          var loader = this._loader;
          var parent = this._parent;
          var children = parent._children;
          var symbolClass = this.class;
          var symbolInfo = this.symbol;
          var props = Object.create(symbolInfo);
          props.name = name;
          props.parent = parent;
          props.depth = depth;
          var instance = symbolClass.createAsSymbol(props);
          if (name && loader && !loader._isAvm2Enabled && !parent.asHasProperty(undefined, name, 0, false)) {
            parent.asSetPublicProperty(name, instance);
          }
          symbolClass.instanceConstructor.call(instance);
          instance._index = children.length;
          children.push(instance);
          if (!loader._isAvm2Enabled) {
            parent._initAvm1Bindings(instance, name, symbolInfo && symbolInfo.events);
            instance._dispatchEvent('init');
            instance._dispatchEvent('construct');
          }
          instance._dispatchEvent('load');
          instance._dispatchEvent('added');
          if (this._stage) {
            instance._invalidate();
          }
          return instance;
        },
        _insertChildAtDepth: function (child, depth) {
          this.addChild(child);
          var name = child._name;
          var loader = this._loader;
          if (name && loader && !loader._isAvm2Enabled && !this._getAS2Object().asHasProperty(undefined, name, 0, true)) {
            this._getAS2Object().asSetPublicProperty(name, child._getAS2Object());
          }
        },
        _initAvm1Bindings: function (instance, name, events) {
          var loader = this._loader;
          var avm1Context = loader._avm1Context;
          var symbolProps = instance.symbol;
          if (symbolProps && symbolProps.variableName) {
            instance._getAS2Object().asSetPublicProperty('variable', symbolProps.variableName);
          }
          if (events) {
            var eventsBound = [];
            for (var i = 0; i < events.length; i++) {
              var event = events[i];
              if (event.eoe) {
                break;
              }
              var fn = function (actionBlock) {
                  return executeActions(actionBlock, avm1Context, this._getAS2Object());
                }.bind(instance, event.actionsData);
              for (var eventName in event) {
                if (eventName.indexOf('on') !== 0 || !event[eventName])
                  continue;
                var avm2EventName = eventName[2].toLowerCase() + eventName.substring(3);
                if (avm2EventName === 'enterFrame') {
                  avm2EventName = 'frameConstructed';
                }
                var avm2EventTarget = instance;
                if (avm2EventName === 'mouseDown' || avm2EventName === 'mouseUp' || avm2EventName === 'mouseMove') {
                  avm2EventTarget = this._stage;
                }
                avm2EventTarget._addEventListener(avm2EventName, fn, false);
                eventsBound.push({
                  name: avm2EventName,
                  fn: fn,
                  target: avm2EventTarget
                });
              }
            }
            if (eventsBound.length > 0) {
              instance._addEventListener('removed', function (eventsBound) {
                for (var i = 0; i < eventsBound.length; i++) {
                  eventsBound[i].target._removeEventListener(eventsBound[i].name, eventsBound[i].fn, false);
                }
              }.bind(instance, eventsBound), false);
            }
          }
          if (name && this._getAS2Object && instance._getAS2Object) {
            this._getAS2Object().asSetPublicProperty(name, instance._getAS2Object());
          }
        },
        _gotoButtonState: function gotoButtonState(stateName) {
        },
        get buttonMode() {
          return this._buttonMode;
        },
        set buttonMode(val) {
          this._buttonMode = val;
        },
        get graphics() {
          return this._graphics;
        },
        get hitArea() {
          return this._hitArea;
        },
        set hitArea(val) {
          if (this._hitArea === val) {
            return;
          }
          if (val && val._hitTarget) {
            val._hitTarget.hitArea = null;
          }
          this._hitArea = val;
          if (val) {
            val._hitTarget = this;
          }
        },
        get soundTransform() {
          notImplemented();
        },
        set soundTransform(val) {
          notImplemented();
        },
        get useHandCursor() {
          return this._useHandCursor;
        },
        set useHandCursor(val) {
          this._useHandCursor = val;
          if (this._stage) {
            this._stage._mouseMoved = true;
          }
        },
        startDrag: function (lockCenter, bounds) {
          notImplemented();
        },
        startTouchDrag: function (touchPointID, lockCenter, bounds) {
          notImplemented();
        },
        stopDrag: function () {
          notImplemented();
        },
        stopTouchDrag: function (touchPointID) {
          notImplemented();
        }
      };
    var desc = Object.getOwnPropertyDescriptor;
    def.__glue__ = {
      native: {
        instance: {
          graphics: desc(def, 'graphics'),
          buttonMode: desc(def, 'buttonMode'),
          dropTarget: desc(def, 'dropTarget'),
          startDrag: def.startDrag,
          stopDrag: def.stopDrag,
          startTouchDrag: def.startTouchDrag,
          stopTouchDrag: def.stopTouchDrag,
          constructChildren: def._constructChildren,
          hitArea: desc(def, 'hitArea'),
          useHandCursor: desc(def, 'useHandCursor'),
          soundTransform: desc(def, 'soundTransform')
        }
      }
    };
    return def;
  }.call(this);
var StageDefinition = function () {
    return {
      __class__: 'flash.display.Stage',
      initialize: function () {
        this._frameRate = 24;
        this._scaleMode = 'showAll';
        this._align = '';
        this._stageWidth = 0;
        this._stageHeight = 0;
        this._quality = 'high';
        this._color = 4294967295;
        this._stage = this;
        this._deferRenderEvent = false;
        this._focus = null;
        this._showDefaultContextMenu = true;
        this._displayState = 'normal';
        this._colorCorrection = 'default';
        this._stageFocusRect = true;
        this._fullScreenSourceRect = null;
        this._wmodeGPU = false;
        this._root = null;
        this._qtree = null;
        this._invalidRegions = new RegionCluster();
        this._mouseMoved = false;
        this._mouseTarget = this;
        this._mouseEvents = [];
        this._cursor = 'auto';
        this._stageVideos = [];
        this._concatenatedTransform.invalid = false;
      },
      _setup: function setup(ctx, options) {
        this._qtree = new QuadTree(0, 0, this._stageWidth, this._stageHeight, null);
        this._invalid = true;
      },
      _addToStage: function addToStage(displayObject) {
        displayObject._stage = this;
        var parent = displayObject._parent;
        displayObject._level = parent._level + 1;
        displayObject._invalid = true;
        var children = displayObject._children;
        for (var i = 0; i < children.length; i++) {
          var child = children[i];
          if (child._stage === null) {
            this._addToStage(child);
          }
        }
        displayObject._dispatchEvent('addedToStage');
      },
      _removeFromStage: function removeFromStage(displayObject) {
        var children = displayObject._children;
        for (var i = 0; i < children.length; i++) {
          var child = children[i];
          if (child._stage) {
            this._removeFromStage(children[i]);
          }
        }
        displayObject._dispatchEvent('removedFromStage');
        displayObject._stage = null;
        displayObject._level = -1;
        if (displayObject._region) {
          this._qtree.remove(displayObject._region);
          this._invalidRegions.insert(displayObject._region);
          displayObject._region = null;
        }
      },
      _processInvalidations: function processInvalidations(refreshStage) {
        var qtree = this._qtree;
        var invalidRegions = this._invalidRegions;
        var stack = [];
        var zindex = 0;
        var children = this._children;
        var i = children.length;
        while (i--) {
          var child = children[i];
          if (refreshStage) {
            child._invalid = true;
          }
          child._invisible = !child._visible;
          stack.push(child);
        }
        while (stack.length) {
          var node = stack.pop();
          var m = node._concatenatedTransform;
          var children = node._children;
          var i = children.length;
          while (i--) {
            var child = children[i];
            if (!flash.display.DisplayObject.class.isInstanceOf(child)) {
              continue;
            }
            if (node._invalid) {
              child._invalid = true;
            }
            if (m.invalid) {
              child._concatenatedTransform.invalid = true;
            }
            child._invisible = node._invisible || !child._visible;
            stack.push(child);
          }
          if (node._level && m.invalid) {
            var m2 = node._currentTransform;
            var m3 = node._parent._concatenatedTransform;
            m.a = m2.a * m3.a + m2.b * m3.c;
            m.b = m2.a * m3.b + m2.b * m3.d;
            m.c = m2.c * m3.a + m2.d * m3.c;
            m.d = m2.d * m3.d + m2.c * m3.b;
            m.tx = m2.tx * m3.a + m3.tx + m2.ty * m3.c;
            m.ty = m2.ty * m3.d + m3.ty + m2.tx * m3.b;
            m.invalid = false;
          }
          var invalidRegion = node._region;
          var currentRegion = node._getRegion(m);
          var hidden = node._invisible || !currentRegion || currentRegion.xMax - currentRegion.xMin === 0 || currentRegion.yMax - currentRegion.yMin === 0 || currentRegion.xMax <= 0 || currentRegion.xMin >= this._stageWidth || currentRegion.yMax <= 0 || currentRegion.yMin >= this._stageHeight;
          if (node._invalid) {
            if (invalidRegion) {
              invalidRegions.insert(invalidRegion);
            }
            if (!hidden && (!invalidRegion || currentRegion.xMin !== invalidRegion.xMin || currentRegion.yMin !== invalidRegion.yMin || currentRegion.xMax !== invalidRegion.xMax || currentRegion.yMax !== invalidRegion.yMax)) {
              invalidRegions.insert(currentRegion);
            }
          }
          if (hidden) {
            if (invalidRegion) {
              qtree.remove(invalidRegion);
              node._region = null;
            }
          } else if (invalidRegion) {
            invalidRegion.xMin = currentRegion.xMin;
            invalidRegion.xMax = currentRegion.xMax;
            invalidRegion.yMin = currentRegion.yMin;
            invalidRegion.yMax = currentRegion.yMax;
            qtree.update(invalidRegion);
          } else {
            currentRegion.obj = node;
            qtree.insert(currentRegion);
            node._region = currentRegion;
          }
          node._zindex = zindex++;
        }
        var invalidPath = new ShapePath();
        if (refreshStage) {
          invalidPath.rect(0, 0, this._stageWidth, this._stageHeight);
          invalidRegions.reset();
          return invalidPath;
        }
        var redrawRegions = invalidRegions.retrieve();
        for (var i = 0; i < redrawRegions.length; i++) {
          var region = redrawRegions[i];
          var xMin = region.xMin - region.xMin % 20 - 40;
          var yMin = region.yMin - region.yMin % 20 - 40;
          var xMax = region.xMax - region.xMax % 20 + 80;
          var yMax = region.yMax - region.yMax % 20 + 80;
          var intersectees = qtree.retrieve(xMin, xMax, yMin, yMax);
          for (var j = 0; j < intersectees.length; j++) {
            var item = intersectees[j];
            item.obj._invalid = true;
          }
          invalidPath.rect(xMin, yMin, xMax - xMin, yMax - yMin);
        }
        invalidRegions.reset();
        return invalidPath;
      },
      _handleMouseButtons: function () {
        if (this._mouseEvents.length === 0) {
          return;
        }
        var eventType = this._mouseEvents.shift();
        switch (eventType) {
        case 'mousedown':
          if (this._mouseTarget._buttonMode) {
            this._mouseTarget._gotoButtonState('down');
          }
          this._mouseTarget._dispatchEvent('mouseDown');
          break;
        case 'mouseup':
          if (this._mouseTarget._buttonMode) {
            this._mouseTarget._gotoButtonState('over');
          }
          this._mouseTarget._dispatchEvent('mouseUp');
          break;
        }
      },
      _handleMouse: function handleMouse() {
        var mouseX = this._mouseX;
        var mouseY = this._mouseY;
        var candidates = this._qtree.retrieve(mouseX, mouseX, mouseY, mouseY);
        var objectsUnderMouse = [];
        for (var i = 0; i < candidates.length; i++) {
          var item = candidates[i];
          var displayObject = item.obj;
          var isUnderMouse = false;
          if (flash.display.SimpleButton.class.isInstanceOf(displayObject)) {
            if (!displayObject._enabled) {
              continue;
            }
            var hitArea = displayObject._hitTestState;
            hitArea._parent = displayObject;
            isUnderMouse = hitArea._hitTest(true, mouseX, mouseY, true);
            hitArea._parent = null;
          } else {
            isUnderMouse = displayObject._hitTest(true, mouseX, mouseY, true);
          }
          if (isUnderMouse) {
            var currentNode = displayObject;
            var lastEnabled = null;
            if (!flash.display.InteractiveObject.class.isInstanceOf(currentNode)) {
              lastEnabled = currentNode;
              currentNode = currentNode._parent;
            }
            do {
              if (!currentNode._mouseEnabled) {
                lastEnabled = null;
              } else if (lastEnabled === null) {
                lastEnabled = currentNode;
              }
              currentNode = currentNode._parent;
            } while (currentNode);
            objectsUnderMouse.push(lastEnabled);
          }
        }
        var target;
        if (objectsUnderMouse.length) {
          objectsUnderMouse.sort(sortByZindex);
          var i = objectsUnderMouse.length;
          while (i--) {
            target = null;
            var currentNode = objectsUnderMouse[i];
            if (!flash.display.InteractiveObject.class.isInstanceOf(currentNode)) {
              var j = i;
              while (j--) {
                if (objectsUnderMouse[j]._parent === currentNode._parent && flash.display.InteractiveObject.class.isInstanceOf(objectsUnderMouse[j])) {
                  currentNode = objectsUnderMouse[j];
                  i = j;
                }
              }
            }
            do {
              if (flash.display.InteractiveObject.class.isInstanceOf(currentNode)) {
                if ((!target || !currentNode._mouseChildren) && !currentNode._hitArea) {
                  target = currentNode;
                }
              }
              currentNode = currentNode._parent;
            } while (currentNode);
            if (target !== objectsUnderMouse[i] && flash.display.SimpleButton.class.isInstanceOf(target)) {
              continue;
            }
            break;
          }
        }
        if (!target) {
          target = this;
        } else if (target._hitTarget) {
          target = target._hitTarget;
        }
        if (target === this._mouseTarget) {
          target._dispatchEvent('mouseMove');
        } else {
          if (this._mouseTarget._buttonMode) {
            this._mouseTarget._gotoButtonState('up');
          }
          this._mouseTarget._dispatchEvent('mouseOut');
          var nodeLeft = this._mouseTarget;
          var containerLeft = nodeLeft._parent;
          var nodeEntered = target;
          var containerEntered = nodeEntered._parent;
          var cursor = 'auto';
          while (nodeLeft._level >= 0 && nodeLeft !== containerEntered) {
            if (nodeLeft._hasEventListener('rollOut')) {
              nodeLeft._dispatchEvent('rollOut');
            }
            nodeLeft = nodeLeft._parent;
          }
          while (nodeEntered._level >= 0 && nodeEntered !== containerLeft) {
            if (nodeEntered._hasEventListener('rollOver')) {
              nodeEntered._dispatchEvent('rollOver');
            }
            if (nodeEntered._buttonMode && nodeEntered._useHandCursor) {
              cursor = 'pointer';
            }
            nodeEntered = nodeEntered._parent;
          }
          if (target._buttonMode) {
            target._gotoButtonState('over');
          }
          target._dispatchEvent('mouseOver');
          this._mouseTarget = target;
          this._cursor = cursor;
        }
      },
      _as2SetLevel: function (level, loader) {
        somewhatImplemented('Stage._as2SetLevel');
        this.addChild(loader);
      },
      __glue__: {
        native: {
          instance: {
            invalidate: function invalidate() {
              this._invalid = true;
              this._deferRenderEvent = true;
            },
            isFocusInaccessible: function isFocusInaccessible() {
              notImplemented('Stage.isFocusInaccessible');
            },
            set_displayState: function set_displayState(value) {
              somewhatImplemented('Stage.set_displayState');
              this._displayState = value;
            },
            get_simulatedFullScreenWidth: function get_simulatedFullScreenWidth() {
              notImplemented('Stage.get_simulatedFullScreenWidth');
            },
            get_simulatedFullScreenHeight: function get_simulatedFullScreenHeight() {
              notImplemented('Stage.get_simulatedFullScreenHeight');
            },
            removeChildAt: function removeChildAt(index) {
              notImplemented('Stage.removeChildAt');
            },
            swapChildrenAt: function swapChildrenAt(index1, index2) {
              notImplemented('Stage.swapChildrenAt');
            },
            requireOwnerPermissions: function requireOwnerPermissions() {
              somewhatImplemented('Stage.requireOwnerPermissions');
            },
            frameRate: {
              get: function frameRate() {
                return this._frameRate;
              },
              set: function frameRate(value) {
                this._frameRate = value;
              }
            },
            scaleMode: {
              get: function scaleMode() {
                return this._scaleMode;
              },
              set: function scaleMode(value) {
                this._scaleMode = value;
                this._invalid = true;
              }
            },
            align: {
              get: function align() {
                return this._align;
              },
              set: function align(value) {
                this._align = value;
                this._invalid = true;
              }
            },
            stageWidth: {
              get: function stageWidth() {
                return this._stageWidth / 20;
              },
              set: function stageWidth(value) {
                notImplemented('Stage.stageWidth');
                this._stageWidth = value * 20 | 0;
              }
            },
            stageHeight: {
              get: function stageHeight() {
                return this._stageHeight / 20;
              },
              set: function stageHeight(value) {
                notImplemented('Stage.stageHeight');
                this._stageHeight = value * 20 | 0;
              }
            },
            showDefaultContextMenu: {
              get: function showDefaultContextMenu() {
                return this._showDefaultContextMenu;
              },
              set: function showDefaultContextMenu(value) {
                somewhatImplemented('Stage.showDefaultContextMenu');
                this._showDefaultContextMenu = value;
              }
            },
            focus: {
              get: function focus() {
                return this._focus;
              },
              set: function focus(newFocus) {
                somewhatImplemented('Stage.focus');
                this._focus = newFocus;
              }
            },
            colorCorrection: {
              get: function colorCorrection() {
                return this._colorCorrection;
              },
              set: function colorCorrection(value) {
                notImplemented('Stage.colorCorrection');
                this._colorCorrection = value;
              }
            },
            colorCorrectionSupport: {
              get: function colorCorrectionSupport() {
                return false;
              }
            },
            stageFocusRect: {
              get: function stageFocusRect() {
                return this._stageFocusRect;
              },
              set: function stageFocusRect(on) {
                somewhatImplemented('Stage.stageFocusRect');
                this._stageFocusRect = on;
              }
            },
            quality: {
              get: function quality() {
                return this._quality;
              },
              set: function quality(value) {
                somewhatImplemented('Stage.stageFocusRect');
                this._quality = value;
              }
            },
            displayState: {
              get: function displayState() {
                return this._displayState;
              },
              set: function displayState(value) {
                this._displayState = value;
              }
            },
            simulatedDisplayState: {
              get: function simulatedDisplayState() {
                notImplemented('Stage.simulatedDisplayState');
                return this._simulatedDisplayState;
              },
              set: function simulatedDisplayState(value) {
                notImplemented('Stage.simulatedDisplayState');
                this._simulatedDisplayState = value;
              }
            },
            fullScreenSourceRect: {
              get: function fullScreenSourceRect() {
                return this._fullScreenSourceRect;
              },
              set: function fullScreenSourceRect(value) {
                notImplemented('Stage.fullScreenSourceRect');
                this._fullScreenSourceRect = value;
              }
            },
            simulatedFullScreenSourceRect: {
              get: function simulatedFullScreenSourceRect() {
                notImplemented('Stage.simulatedFullScreenSourceRect');
                return this._simulatedFullScreenSourceRect;
              },
              set: function simulatedFullScreenSourceRect(value) {
                notImplemented('Stage.simulatedFullScreenSourceRect');
                this._simulatedFullScreenSourceRect = value;
              }
            },
            stageVideos: {
              get: function stageVideos() {
                somewhatImplemented('Stage.stageVideos');
                return this._stageVideos;
              }
            },
            stage3Ds: {
              get: function stage3Ds() {
                notImplemented('Stage.stage3Ds');
                return this._stage3Ds;
              }
            },
            color: {
              get: function color() {
                return this._color;
              },
              set: function color(color) {
                this._color = color;
                this._invalid = true;
              }
            },
            fullScreenWidth: {
              get: function fullScreenWidth() {
                notImplemented('Stage.fullScreenWidth');
                return this._fullScreenWidth;
              }
            },
            fullScreenHeight: {
              get: function fullScreenHeight() {
                notImplemented('Stage.fullScreenHeight');
                return this._fullScreenHeight;
              }
            },
            wmodeGPU: {
              get: function wmodeGPU() {
                somewhatImplemented('Stage.wmodeGPU');
                return this._wmodeGPU;
              }
            },
            softKeyboardRect: {
              get: function softKeyboardRect() {
                notImplemented('Stage.softKeyboardRect');
                return this._softKeyboardRect;
              }
            },
            allowsFullScreen: {
              get: function allowsFullScreen() {
                return false;
              }
            },
            displayContextInfo: {
              get: function displayContextInfo() {
                notImplemented('Stage.displayContextInfo');
                return this._displayContextInfo;
              }
            }
          }
        }
      }
    };
  }.call(this);
{
  var EventDefinition = function () {
      return {
        __class__: 'flash.events.Event',
        initialize: function () {
          this._stopPropagation = false;
          this._stopImmediatePropagation = false;
          this._isDefaultPrevented = false;
          this._target = null;
          this._currentTarget = null;
          this._eventPhase = 2;
        },
        __glue__: {
          native: {
            instance: {
              ctor: function ctor(type, bubbles, cancelable) {
                Counter.count('Event: ' + type);
                this._type = type;
                this._bubbles = bubbles;
                this._cancelable = cancelable;
              },
              stopPropagation: function stopPropagation() {
                this._stopPropagation = true;
              },
              stopImmediatePropagation: function stopImmediatePropagation() {
                this._stopImmediatePropagation = this._stopPropagation = true;
              },
              preventDefault: function preventDefault() {
                if (this._cancelable)
                  this._isDefaultPrevented = true;
              },
              isDefaultPrevented: function isDefaultPrevented() {
                return this._isDefaultPrevented;
              },
              type: {
                get: function type() {
                  return this._type;
                }
              },
              bubbles: {
                get: function bubbles() {
                  return this._bubbles;
                }
              },
              cancelable: {
                get: function cancelable() {
                  return this._cancelable;
                }
              },
              target: {
                get: function target() {
                  return this._target;
                }
              },
              currentTarget: {
                get: function currentTarget() {
                  return this._currentTarget;
                }
              },
              eventPhase: {
                get: function eventPhase() {
                  return this._eventPhase;
                }
              }
            }
          },
          script: {
            static: Glue.ALL,
            instance: {
              clone: 'open public clone'
            }
          }
        }
      };
    }.call(this);
}
var EventDispatcherDefinition = function () {
    var mouseEvents = {
        click: true,
        contextMenu: true,
        doubleClick: true,
        middleClick: true,
        middleMouseDown: true,
        middleMouseUp: true,
        mouseDown: true,
        mouseMove: true,
        mouseOut: true,
        mouseOver: true,
        mouseUp: true,
        mouseWheel: true,
        releaseOutside: true,
        rightClick: true,
        rightMouseDown: true,
        rightMouseUp: true,
        rollOut: false,
        rollOver: false
      };
    function doDispatchEvent(dispatcher, event, eventClass, bubbles) {
      var target = dispatcher._target;
      var type = event._type || event;
      var listeners = dispatcher._listeners[type];
      if (bubbles || typeof event === 'string' && mouseEvents[event] || event._bubbles) {
        var ancestors = [];
        var currentNode = target._parent;
        while (currentNode) {
          if (currentNode._hasEventListener(type)) {
            ancestors.push(currentNode);
          }
          currentNode = currentNode._parent;
        }
        if (!listeners && !ancestors.length) {
          return true;
        }
        var keepPropagating = true;
        var i = ancestors.length;
        while (i-- && keepPropagating) {
          var currentTarget = ancestors[i];
          var queue = currentTarget._captureListeners[type];
          keepPropagating = processListeners(queue, event, eventClass, bubbles, target, currentTarget, 1);
        }
        if (listeners && keepPropagating) {
          keepPropagating = processListeners(listeners, event, eventClass, bubbles, target);
        }
        for (var i = 0; i < ancestors.length && keepPropagating; i++) {
          var currentTarget = ancestors[i];
          var queue = currentTarget._listeners[type];
          keepPropagating = processListeners(queue, event, eventClass, bubbles, target, currentTarget, 3);
        }
      } else if (listeners) {
        processListeners(listeners, event, eventClass, bubbles, target);
      }
      return !event._isDefaultPrevented;
    }
    function processListeners(queue, event, eventClass, bubbles, target, currentTarget, eventPhase) {
      if (queue) {
        queue = queue.slice();
        var needsInit = true;
        try {
          for (var i = 0; i < queue.length; i++) {
            var item = queue[i];
            var methodInfo = item.handleEvent.methodInfo;
            if (methodInfo) {
              if (methodInfo.parameters.length) {
                if (!methodInfo.parameters[0].isUsed) {
                  item.handleEvent();
                  continue;
                }
              }
            }
            if (needsInit) {
              if (typeof event === 'string') {
                if (eventClass) {
                  event = new eventClass(event);
                } else {
                  if (mouseEvents[event]) {
                    event = new flash.events.MouseEvent(event, mouseEvents[event]);
                    if (target._stage) {
                      event._localX = target.mouseX;
                      event._localY = target.mouseY;
                    }
                  } else {
                    event = new flash.events.Event(event);
                  }
                }
              } else if (event._target) {
                event = event.clone();
              }
              event._target = target;
              event._currentTarget = currentTarget || target;
              event._eventPhase = eventPhase || 2;
              needsInit = false;
            }
            item.handleEvent(event);
            if (event._stopImmediatePropagation) {
              break;
            }
          }
        } catch (e) {
          avm2.exceptions.push({
            source: 'avm2',
            message: e.message,
            stack: e.stack
          });
          throw e;
        }
      }
      return !event._stopPropagation;
    }
    return {
      __class__: 'flash.events.EventDispatcher',
      initialize: function () {
        this._target = this;
        this._listeners = {};
        this._captureListeners = {};
      },
      _addEventListenerImpl: function addEventListenerImpl(type, listener, useCapture, priority) {
        if (typeof listener !== 'function') {
          throwError('TypeError', Errors.CheckTypeFailedError, listener, 'Function');
        }
        var listeners = useCapture ? this._captureListeners : this._listeners;
        var queue = listeners[type];
        var listenerObj = {
            handleEvent: listener,
            priority: priority || 0
          };
        if (queue) {
          var level = queue.length;
          var i = level;
          while (i--) {
            var item = queue[i];
            if (item.handleEvent === listener) {
              return;
            }
            if (priority > item.priority) {
              level = i;
            }
          }
          queue.splice(level, 0, listenerObj);
        } else {
          listeners[type] = [
            listenerObj
          ];
        }
      },
      _addEventListener: function addEventListener(type, listener, useCapture, priority) {
        this._addEventListenerImpl(type, listener, useCapture, priority);
      },
      _removeEventListenerImpl: function removeEventListenerImpl(type, listener, useCapture) {
        if (typeof listener !== 'function') {
          throwError('TypeError', Errors.CheckTypeFailedError, listener, 'Function');
        }
        var listeners = useCapture ? this._captureListeners : this._listeners;
        var queue = listeners[type];
        if (queue) {
          for (var i = 0; i < queue.length; i++) {
            var item = queue[i];
            if (item.handleEvent === listener) {
              queue.splice(i, 1);
              if (!queue.length) {
                listeners[type] = null;
              }
              return;
            }
          }
        }
      },
      _removeEventListener: function removeEventListener(type, listener, useCapture) {
        this._removeEventListenerImpl(type, listener, useCapture);
      },
      _hasEventListener: function hasEventListener(type) {
        return this._listeners[type] || this._captureListeners[type];
      },
      _dispatchEvent: function dispatchEvent(event, eventClass, bubbles) {
        doDispatchEvent(this, event, eventClass, bubbles);
      },
      __glue__: {
        native: {
          instance: {
            ctor: function ctor(target) {
              this._target = target || this;
            },
            addEventListener: function addEventListener(type, listener, useCapture, priority, useWeakReference) {
              this._addEventListener(type, listener, useCapture, priority);
            },
            removeEventListener: function removeEventListener(type, listener, useCapture) {
              this._removeEventListener(type, listener, useCapture);
            },
            hasEventListener: function hasEventListener(type) {
              return this._hasEventListener(type);
            },
            willTrigger: function willTrigger(type) {
              var currentNode = this._target;
              do {
                if (currentNode._hasEventListener(type)) {
                  return true;
                }
              } while (currentNode = currentNode._parent);
              return false;
            },
            dispatchEventFunction: function dispatchEventFunction(event) {
              return doDispatchEvent(this, event);
            }
          }
        }
      }
    };
  }.call(this);
var KeyboardEventDefinition = function () {
    return {
      __class__: 'flash.events.KeyboardEvent',
      __glue__: {
        native: {
          instance: {
            updateAfterEvent: function updateAfterEvent() {
              notImplemented('KeyboardEvent.updateAfterEvent');
            },
            charCode: {
              get: function charCode() {
                return this._charCode;
              },
              set: function charCode(value) {
                this._charCode = value;
              }
            },
            ctrlKey: {
              get: function ctrlKey() {
                return this._ctrlKey;
              },
              set: function ctrlKey(value) {
                this._ctrlKey = value;
              }
            },
            altKey: {
              get: function altKey() {
                return this._altKey;
              },
              set: function altKey(value) {
                this._altKey = value;
              }
            },
            shiftKey: {
              get: function shiftKey() {
                return this._shiftKey;
              },
              set: function shiftKey(value) {
                this._shiftKey = value;
              }
            }
          }
        },
        script: {
          static: Glue.ALL,
          instance: {
            keyCode: 'public keyCode'
          }
        }
      }
    };
  }.call(this);
var MouseEventDefinition = function () {
    return {
      __class__: 'flash.events.MouseEvent',
      initialize: function () {
        this._localX = NaN;
        this._localY = NaN;
      },
      __glue__: {
        native: {
          instance: {
            updateAfterEvent: function updateAfterEvent() {
            },
            getStageX: function getStageX() {
              if (this._target) {
                var m = this._target._getConcatenatedTransform(null, false);
                var x = m.a * this._localX + m.c * this._localY + m.tx;
                return x / 20;
              }
              return this._localX / 20;
            },
            getStageY: function getStageY() {
              if (this._target) {
                var m = this._target._getConcatenatedTransform(null, false);
                var y = m.d * this._localY + m.b * this._localX + m.ty;
                return y / 20;
              }
              return this._localY / 20;
            },
            localX: {
              get: function localX() {
                return this._localX / 20;
              },
              set: function localX(value) {
                this._localX = value * 20 | 0;
              }
            },
            localY: {
              get: function localY() {
                return this._localY / 20;
              },
              set: function localY(value) {
                this._localY = value * 20 | 0;
              }
            }
          }
        },
        script: {
          static: Glue.ALL
        }
      }
    };
  }.call(this);
var TextEventDefinition = function () {
    return {
      __class__: 'flash.events.TextEvent',
      __glue__: {
        native: {
          instance: {
            copyNativeData: function copyNativeData(other) {
              notImplemented('TextEvent.copyNativeData');
            }
          }
        }
      }
    };
  }.call(this);
var TimerEventDefinition = function () {
    return {
      __class__: 'flash.events.TimerEvent',
      __glue__: {
        native: {
          instance: {
            updateAfterEvent: function updateAfterEvent() {
              notImplemented('TimerEvent.updateAfterEvent');
            }
          }
        }
      }
    };
  }.call(this);
{
  var ExternalInterfaceDefinition = function () {
      function getAvailable() {
        return true;
      }
      var initialized = false;
      var registeredCallbacks = {};
      function callIn(functionName, args) {
        if (!registeredCallbacks.hasOwnProperty(functionName))
          return;
        return registeredCallbacks[functionName](functionName, args);
      }
      return {
        __class__: 'flash.external.ExternalInterface',
        initialize: function () {
        },
        __glue__: {
          native: {
            static: {
              _initJS: function _initJS() {
                if (initialized)
                  return;
                TelemetryService.reportTelemetry({
                  topic: 'feature',
                  feature: EXTERNAL_INTERFACE_FEATURE
                });
                initialized = true;
                FirefoxCom.initJS(callIn);
              },
              _getPropNames: function _getPropNames(obj) {
                var keys = [];
                forEachPublicProperty(obj, function (key) {
                  keys.push(key);
                });
                return keys;
              },
              _addCallback: function _addCallback(functionName, closure, hasNullCallback) {
                FirefoxCom.request('externalCom', {
                  action: 'register',
                  functionName: functionName,
                  remove: hasNullCallback
                });
                if (hasNullCallback) {
                  delete registeredCallbacks[functionName];
                } else {
                  registeredCallbacks[functionName] = closure;
                }
              },
              _evalJS: function _evalJS(expression) {
                return FirefoxCom.requestSync('externalCom', {
                  action: 'eval',
                  expression: expression
                });
              },
              _callOut: function _callOut(request) {
                return FirefoxCom.requestSync('externalCom', {
                  action: 'call',
                  request: request
                });
              },
              available: {
                get: getAvailable
              },
              objectID: {
                get: function objectID() {
                  return FirefoxCom.requestSync('externalCom', {
                    action: 'getId'
                  });
                }
              },
              activeX: {
                get: function activeX() {
                  return false;
                }
              }
            },
            instance: {}
          }
        }
      };
    }.call(this);
}
{
  var BevelFilterDefinition = function () {
      var def = {
          __class__: 'flash.filters.BevelFilter',
          initialize: function () {
          },
          _updateFilterBounds: function (bounds) {
          }
        };
      def.__glue__ = {};
      return def;
    }.call(this);
}
var BitmapFilterDefinition = function () {
    var def = {
        __class__: 'flash.filters.BitmapFilter',
        initialize: function () {
        },
        _updateFilterBounds: function (bounds) {
        }
      };
    def.__glue__ = {};
    return def;
  }.call(this);
var BlurFilterDefinition = function () {
    return {
      __class__: 'flash.filters.BlurFilter',
      initialize: function () {
      },
      _updateFilterBounds: function (bounds) {
        var bx = this._blurX * this._quality * 20;
        var by = this._blurY * this._quality * 20;
        bounds.xMin -= bx;
        bounds.xMax += bx;
        bounds.yMin -= by;
        bounds.yMax += by;
      },
      __glue__: {
        native: {
          static: {},
          instance: {
            blurX: {
              get: function blurX() {
                return this._blurX;
              },
              set: function blurX(value) {
                this._blurX = value;
              }
            },
            blurY: {
              get: function blurY() {
                return this._blurY;
              },
              set: function blurY(value) {
                this._blurY = value;
              }
            },
            quality: {
              get: function quality() {
                return this._quality;
              },
              set: function quality(value) {
                this._quality = value;
              }
            }
          }
        }
      }
    };
  }.call(this);
var ColorMatrixFilterDefinition = function () {
    return {
      __class__: 'flash.filters.ColorMatrixFilter',
      initialize: function () {
      },
      _updateFilterBounds: function (bounds) {
      },
      __glue__: {
        native: {
          instance: {
            matrix: {
              get: function matrix() {
                return this._matrix;
              },
              set: function matrix(value) {
                this._matrix = value;
              }
            }
          }
        }
      }
    };
  }.call(this);
var ConvolutionFilterDefinition = function () {
    var def = {
        __class__: 'flash.filters.ConvolutionFilter',
        initialize: function () {
        },
        _updateFilterBounds: function (bounds) {
        }
      };
    def.__glue__ = {};
    return def;
  }.call(this);
var DisplacementMapFilterDefinition = function () {
    var def = {
        __class__: 'flash.filters.DisplacementMapFilter',
        initialize: function () {
        },
        _updateFilterBounds: function (bounds) {
        }
      };
    def.__glue__ = {};
    return def;
  }.call(this);
var DropShadowFilterDefinition = function () {
    return {
      __class__: 'flash.filters.DropShadowFilter',
      initialize: function () {
      },
      _updateFilterBounds: function (bounds) {
        var a = this._angle * Math.PI / 180;
        var dy = Math.sin(a) * this._distance;
        var dx = Math.cos(a) * this._distance;
        var bx = this._blurX * this._quality * 20;
        var by = this._blurY * this._quality * 20;
        bounds.xMin -= bx - (dx > 0 ? 0 : dx);
        bounds.xMax += bx + Math.abs(dx);
        bounds.yMin -= by - (dy > 0 ? 0 : dy);
        bounds.yMax += by + Math.abs(dy);
      },
      __glue__: {
        native: {
          instance: {
            distance: {
              get: function distance() {
                return this._distance;
              },
              set: function distance(value) {
                this._distance = value;
              }
            },
            angle: {
              get: function angle() {
                return this._angle;
              },
              set: function angle(value) {
                this._angle = value;
              }
            },
            color: {
              get: function color() {
                return this._color;
              },
              set: function color(value) {
                this._color = value;
              }
            },
            alpha: {
              get: function alpha() {
                return this._alpha;
              },
              set: function alpha(value) {
                this._alpha = value;
              }
            },
            blurX: {
              get: function blurX() {
                return this._blurX;
              },
              set: function blurX(value) {
                this._blurX = value;
              }
            },
            blurY: {
              get: function blurY() {
                return this._blurY;
              },
              set: function blurY(value) {
                this._blurY = value;
              }
            },
            hideObject: {
              get: function hideObject() {
                return this._hideObject;
              },
              set: function hideObject(value) {
                this._hideObject = value;
              }
            },
            inner: {
              get: function inner() {
                return this._inner;
              },
              set: function inner(value) {
                this._inner = value;
              }
            },
            knockout: {
              get: function knockout() {
                return this._knockout;
              },
              set: function knockout(value) {
                this._knockout = value;
              }
            },
            quality: {
              get: function quality() {
                return this._quality;
              },
              set: function quality(value) {
                this._quality = value;
              }
            },
            strength: {
              get: function strength() {
                return this._strength;
              },
              set: function strength(value) {
                this._strength = value;
              }
            }
          }
        }
      }
    };
  }.call(this);
var GlowFilterDefinition = function () {
    return {
      __class__: 'flash.filters.GlowFilter',
      initialize: function () {
      },
      _updateFilterBounds: function (bounds) {
        var bx = this._blurX * this._quality * 20;
        var by = this._blurY * this._quality * 20;
        bounds.xMin -= bx;
        bounds.xMax += bx;
        bounds.yMin -= by;
        bounds.yMax += by;
      },
      __glue__: {
        native: {
          static: {},
          instance: {
            color: {
              get: function color() {
                return this._color;
              },
              set: function color(value) {
                this._color = value;
              }
            },
            alpha: {
              get: function alpha() {
                return this._alpha;
              },
              set: function alpha(value) {
                this._alpha = value;
              }
            },
            blurX: {
              get: function blurX() {
                return this._blurX;
              },
              set: function blurX(value) {
                this._blurX = value;
              }
            },
            blurY: {
              get: function blurY() {
                return this._blurY;
              },
              set: function blurY(value) {
                this._blurY = value;
              }
            },
            inner: {
              get: function inner() {
                return this._inner;
              },
              set: function inner(value) {
                this._inner = value;
              }
            },
            knockout: {
              get: function knockout() {
                return this._knockout;
              },
              set: function knockout(value) {
                this._knockout = value;
              }
            },
            quality: {
              get: function quality() {
                return this._quality;
              },
              set: function quality(value) {
                this._quality = value;
              }
            },
            strength: {
              get: function strength() {
                return this._strength;
              },
              set: function strength(value) {
                this._strength = value;
              }
            }
          }
        }
      }
    };
  }.call(this);
var GradientBevelFilterDefinition = function () {
    var def = {
        __class__: 'flash.filters.GradientBevelFilter',
        initialize: function () {
        },
        _updateFilterBounds: function (bounds) {
        }
      };
    def.__glue__ = {};
    return def;
  }.call(this);
var GradientGlowFilterDefinition = function () {
    var def = {
        __class__: 'flash.filters.GradientGlowFilter',
        initialize: function () {
        },
        _updateFilterBounds: function (bounds) {
        }
      };
    def.__glue__ = {};
    return def;
  }.call(this);
var ShaderFilterDefinition = function () {
    var def = {
        __class__: 'flash.filters.ShaderFilter',
        initialize: function () {
        },
        _updateFilterBounds: function (bounds) {
        }
      };
    def.__glue__ = {};
    return def;
  }.call(this);
{
  var ColorTransformDefinition = function () {
      return {
        __class__: 'flash.geom.ColorTransform',
        __glue__: {
          script: {
            instance: Glue.ALL
          }
        }
      };
    }.call(this);
}
var MatrixDefinition = function () {
    return {
      __class__: 'flash.geom.Matrix',
      __glue__: {
        script: {
          instance: Glue.ALL
        }
      }
    };
  }.call(this);
var Matrix3DDefinition = function () {
    var precision = 1e-7;
    var transposeTransform = new Uint32Array([
        0,
        4,
        8,
        12,
        1,
        5,
        9,
        13,
        2,
        6,
        10,
        14,
        3,
        7,
        11,
        15
      ]);
    function getRotationMatrix(theta, u, v, w, a, b, c) {
      var u2 = u * u, v2 = v * v, w2 = w * w;
      var L2 = u2 + v2 + w2, L = Math.sqrt(L2);
      u /= L;
      v /= L;
      w /= L;
      u2 /= L2;
      v2 /= L2;
      w2 /= L2;
      var cos = Math.cos(theta), sin = Math.sin(theta);
      return new flash.geom.Matrix3D([
        u2 + (v2 + w2) * cos,
        u * v * (1 - cos) + w * sin,
        u * w * (1 - cos) - v * sin,
        0,
        u * v * (1 - cos) - w * sin,
        v2 + (u2 + w2) * cos,
        v * w * (1 - cos) + u * sin,
        0,
        u * w * (1 - cos) + v * sin,
        v * w * (1 - cos) - u * sin,
        w2 + (u2 + v2) * cos,
        0,
        (a * (v2 + w2) - u * (b * v + c * w)) * (1 - cos) + (b * w - c * v) * sin,
        (b * (u2 + w2) - v * (a * u + c * w)) * (1 - cos) + (c * u - a * w) * sin,
        (c * (u2 + v2) - w * (a * u + b * v)) * (1 - cos) + (a * v - b * u) * sin,
        1
      ]);
    }
    return {
      __class__: 'flash.geom.Matrix3D',
      initialize: function () {
      },
      __glue__: {
        native: {
          static: {
            interpolate: function interpolate(thisMat, toMat, percent) {
              notImplemented('Matrix3D.interpolate');
            }
          },
          instance: {
            ctor: function ctor(v) {
              this._matrix = new Float32Array(16);
              if (v && v.length >= 16) {
                this.copyRawDataFrom(v, 0, false);
              } else {
                this.identity();
              }
            },
            clone: function clone() {
              return new flash.geom.Matrix3D(this._matrix);
            },
            copyToMatrix3D: function copyToMatrix3D(dest) {
              dest._matrix.set(this._matrix);
            },
            append: function append(lhs) {
              var ma = lhs._matrix, mb = this._matrix, m = this._matrix;
              var ma11 = ma[0], ma12 = ma[4], ma13 = ma[8], ma14 = ma[12], ma21 = ma[1], ma22 = ma[5], ma23 = ma[9], ma24 = ma[13], ma31 = ma[2], ma32 = ma[6], ma33 = ma[10], ma34 = ma[14], ma41 = ma[3], ma42 = ma[7], ma43 = ma[11], ma44 = ma[15];
              var mb11 = mb[0], mb12 = mb[4], mb13 = mb[8], mb14 = mb[12], mb21 = mb[1], mb22 = mb[5], mb23 = mb[9], mb24 = mb[13], mb31 = mb[2], mb32 = mb[6], mb33 = mb[10], mb34 = mb[14], mb41 = mb[3], mb42 = mb[7], mb43 = mb[11], mb44 = mb[15];
              m[0] = ma11 * mb11 + ma12 * mb21 + ma13 * mb31 + ma14 * mb41;
              m[1] = ma21 * mb11 + ma22 * mb21 + ma23 * mb31 + ma24 * mb41;
              m[2] = ma31 * mb11 + ma32 * mb21 + ma33 * mb31 + ma34 * mb41;
              m[3] = ma41 * mb11 + ma42 * mb21 + ma43 * mb31 + ma44 * mb41;
              m[4] = ma11 * mb12 + ma12 * mb22 + ma13 * mb32 + ma14 * mb42;
              m[5] = ma21 * mb12 + ma22 * mb22 + ma23 * mb32 + ma24 * mb42;
              m[6] = ma31 * mb12 + ma32 * mb22 + ma33 * mb32 + ma34 * mb42;
              m[7] = ma41 * mb12 + ma42 * mb22 + ma43 * mb32 + ma44 * mb42;
              m[8] = ma11 * mb13 + ma12 * mb23 + ma13 * mb33 + ma14 * mb43;
              m[9] = ma21 * mb13 + ma22 * mb23 + ma23 * mb33 + ma24 * mb43;
              m[10] = ma31 * mb13 + ma32 * mb23 + ma33 * mb33 + ma34 * mb43;
              m[11] = ma41 * mb13 + ma42 * mb23 + ma43 * mb33 + ma44 * mb43;
              m[12] = ma11 * mb14 + ma12 * mb24 + ma13 * mb34 + ma14 * mb44;
              m[13] = ma21 * mb14 + ma22 * mb24 + ma23 * mb34 + ma24 * mb44;
              m[14] = ma31 * mb14 + ma32 * mb24 + ma33 * mb34 + ma34 * mb44;
              m[15] = ma41 * mb14 + ma42 * mb24 + ma43 * mb34 + ma44 * mb44;
            },
            prepend: function prepend(rhs) {
              var ma = this._matrix, mb = rhs._matrix, m = this._matrix;
              var ma11 = ma[0], ma12 = ma[4], ma13 = ma[8], ma14 = ma[12], ma21 = ma[1], ma22 = ma[5], ma23 = ma[9], ma24 = ma[13], ma31 = ma[2], ma32 = ma[6], ma33 = ma[10], ma34 = ma[14], ma41 = ma[3], ma42 = ma[7], ma43 = ma[11], ma44 = ma[15];
              var mb11 = mb[0], mb12 = mb[4], mb13 = mb[8], mb14 = mb[12], mb21 = mb[1], mb22 = mb[5], mb23 = mb[9], mb24 = mb[13], mb31 = mb[2], mb32 = mb[6], mb33 = mb[10], mb34 = mb[14], mb41 = mb[3], mb42 = mb[7], mb43 = mb[11], mb44 = mb[15];
              m[0] = ma11 * mb11 + ma12 * mb21 + ma13 * mb31 + ma14 * mb41;
              m[1] = ma21 * mb11 + ma22 * mb21 + ma23 * mb31 + ma24 * mb41;
              m[2] = ma31 * mb11 + ma32 * mb21 + ma33 * mb31 + ma34 * mb41;
              m[3] = ma41 * mb11 + ma42 * mb21 + ma43 * mb31 + ma44 * mb41;
              m[4] = ma11 * mb12 + ma12 * mb22 + ma13 * mb32 + ma14 * mb42;
              m[5] = ma21 * mb12 + ma22 * mb22 + ma23 * mb32 + ma24 * mb42;
              m[6] = ma31 * mb12 + ma32 * mb22 + ma33 * mb32 + ma34 * mb42;
              m[7] = ma41 * mb12 + ma42 * mb22 + ma43 * mb32 + ma44 * mb42;
              m[8] = ma11 * mb13 + ma12 * mb23 + ma13 * mb33 + ma14 * mb43;
              m[9] = ma21 * mb13 + ma22 * mb23 + ma23 * mb33 + ma24 * mb43;
              m[10] = ma31 * mb13 + ma32 * mb23 + ma33 * mb33 + ma34 * mb43;
              m[11] = ma41 * mb13 + ma42 * mb23 + ma43 * mb33 + ma44 * mb43;
              m[12] = ma11 * mb14 + ma12 * mb24 + ma13 * mb34 + ma14 * mb44;
              m[13] = ma21 * mb14 + ma22 * mb24 + ma23 * mb34 + ma24 * mb44;
              m[14] = ma31 * mb14 + ma32 * mb24 + ma33 * mb34 + ma34 * mb44;
              m[15] = ma41 * mb14 + ma42 * mb24 + ma43 * mb34 + ma44 * mb44;
            },
            invert: function invert() {
              var d = this.determinant;
              if (Math.abs(d) < precision) {
                return false;
              }
              d = 1 / d;
              var m = this._matrix;
              var m11 = m[0], m12 = m[1], m13 = m[2], m14 = m[3], m21 = m[4], m22 = m[5], m23 = m[6], m24 = m[7], m31 = m[8], m32 = m[9], m33 = m[10], m34 = m[11], m41 = m[12], m42 = m[13], m43 = m[14], m44 = m[15];
              m[0] = d * (m22 * (m33 * m44 - m43 * m34) - m32 * (m23 * m44 - m43 * m24) + m42 * (m23 * m34 - m33 * m24));
              m[1] = -d * (m12 * (m33 * m44 - m43 * m34) - m32 * (m13 * m44 - m43 * m14) + m42 * (m13 * m34 - m33 * m14));
              m[2] = d * (m12 * (m23 * m44 - m43 * m24) - m22 * (m13 * m44 - m43 * m14) + m42 * (m13 * m24 - m23 * m14));
              m[3] = -d * (m12 * (m23 * m34 - m33 * m24) - m22 * (m13 * m34 - m33 * m14) + m32 * (m13 * m24 - m23 * m14));
              m[4] = -d * (m21 * (m33 * m44 - m43 * m34) - m31 * (m23 * m44 - m43 * m24) + m41 * (m23 * m34 - m33 * m24));
              m[5] = d * (m11 * (m33 * m44 - m43 * m34) - m31 * (m13 * m44 - m43 * m14) + m41 * (m13 * m34 - m33 * m14));
              m[6] = -d * (m11 * (m23 * m44 - m43 * m24) - m21 * (m13 * m44 - m43 * m14) + m41 * (m13 * m24 - m23 * m14));
              m[7] = d * (m11 * (m23 * m34 - m33 * m24) - m21 * (m13 * m34 - m33 * m14) + m31 * (m13 * m24 - m23 * m14));
              m[8] = d * (m21 * (m32 * m44 - m42 * m34) - m31 * (m22 * m44 - m42 * m24) + m41 * (m22 * m34 - m32 * m24));
              m[9] = -d * (m11 * (m32 * m44 - m42 * m34) - m31 * (m12 * m44 - m42 * m14) + m41 * (m12 * m34 - m32 * m14));
              m[10] = d * (m11 * (m22 * m44 - m42 * m24) - m21 * (m12 * m44 - m42 * m14) + m41 * (m12 * m24 - m22 * m14));
              m[11] = -d * (m11 * (m22 * m34 - m32 * m24) - m21 * (m12 * m34 - m32 * m14) + m31 * (m12 * m24 - m22 * m14));
              m[12] = -d * (m21 * (m32 * m43 - m42 * m33) - m31 * (m22 * m43 - m42 * m23) + m41 * (m22 * m33 - m32 * m23));
              m[13] = d * (m11 * (m32 * m43 - m42 * m33) - m31 * (m12 * m43 - m42 * m13) + m41 * (m12 * m33 - m32 * m13));
              m[14] = -d * (m11 * (m22 * m43 - m42 * m23) - m21 * (m12 * m43 - m42 * m13) + m41 * (m12 * m23 - m22 * m13));
              m[15] = d * (m11 * (m22 * m33 - m32 * m23) - m21 * (m12 * m33 - m32 * m13) + m31 * (m12 * m23 - m22 * m13));
              return true;
            },
            identity: function identity() {
              var m = this._matrix;
              m[0] = m[5] = m[10] = m[15] = 1;
              m[1] = m[2] = m[3] = m[4] = m[6] = m[7] = m[8] = m[9] = m[11] = m[12] = m[13] = m[14] = 0;
            },
            decompose: function decompose(orientationStyle) {
              notImplemented('Matrix3D.decompose');
            },
            recompose: function recompose(components, orientationStyle) {
              notImplemented('Matrix3D.recompose');
            },
            appendTranslation: function appendTranslation(x, y, z) {
              var m = this._matrix;
              var m41 = m[3], m42 = m[7], m43 = m[11], m44 = m[15];
              m[0] += x * m41;
              m[1] += y * m41;
              m[2] += z * m41;
              m[4] += x * m42;
              m[5] += y * m42;
              m[6] += z * m42;
              m[8] += x * m43;
              m[9] += y * m43;
              m[10] += z * m43;
              m[12] += x * m44;
              m[13] += y * m44;
              m[14] += z * m44;
            },
            appendRotation: function appendRotation(degrees, axis, pivotPoint) {
              this.append(getRotationMatrix(degrees / 180 * Math.PI, axis.x, axis.y, axis.z, pivotPoint ? pivotPoint.x : 0, pivotPoint ? pivotPoint.y : 0, pivotPoint ? pivotPoint.z : 0));
            },
            appendScale: function appendScale(xScale, yScale, zScale) {
              var m = this._matrix;
              m[0] *= xScale;
              m[1] *= yScale;
              m[2] *= zScale;
              m[4] *= xScale;
              m[5] *= yScale;
              m[6] *= zScale;
              m[8] *= xScale;
              m[9] *= yScale;
              m[10] *= zScale;
              m[12] *= xScale;
              m[13] *= yScale;
              m[14] *= zScale;
            },
            prependTranslation: function prependTranslation(x, y, z) {
              var m = this._matrix;
              var m11 = m[0], m12 = m[4], m13 = m[8], m14 = m[12], m21 = m[1], m22 = m[5], m23 = m[9], m24 = m[13], m31 = m[2], m32 = m[6], m33 = m[10], m34 = m[14], m41 = m[3], m42 = m[7], m43 = m[11], m44 = m[15];
              m[12] += m11 * x + m12 * y + m13 * z;
              m[13] += m21 * x + m22 * y + m23 * z;
              m[14] += m31 * x + m32 * y + m33 * z;
              m[15] += m41 * x + m42 * y + m43 * z;
            },
            prependRotation: function prependRotation(degrees, axis, pivotPoint) {
              this.prepend(getRotationMatrix(degrees / 180 * Math.PI, axis.x, axis.y, axis.z, pivotPoint ? pivotPoint.x : 0, pivotPoint ? pivotPoint.y : 0, pivotPoint ? pivotPoint.z : 0));
            },
            prependScale: function prependScale(xScale, yScale, zScale) {
              var m = this._matrix;
              m[0] *= xScale;
              m[1] *= xScale;
              m[2] *= xScale;
              m[3] *= xScale;
              m[4] *= yScale;
              m[5] *= yScale;
              m[6] *= yScale;
              m[7] *= yScale;
              m[8] *= zScale;
              m[9] *= zScale;
              m[10] *= zScale;
              m[11] *= zScale;
            },
            transformVector: function transformVector(v) {
              var m = this._matrix;
              var x = v.x, y = v.y, z = v.z;
              return new flash.geom.Vector3D(m[0] * x + m[4] * y + m[8] * z + m[12], m[1] * x + m[5] * y + m[9] * z + m[13], m[2] * x + m[6] * y + m[10] * z + m[14]);
            },
            deltaTransformVector: function deltaTransformVector(v) {
              var m = this._matrix;
              var x = v.x, y = v.y, z = v.z;
              return new flash.geom.Vector3D(m[0] * x + m[4] * y + m[8] * z, m[1] * x + m[5] * y + m[9] * z, m[2] * x + m[6] * y + m[10] * z);
            },
            transformVectors: function transformVectors(vin, vout) {
              var m = this._matrix;
              var m11 = m[0], m12 = m[4], m13 = m[8], m14 = m[12], m21 = m[1], m22 = m[5], m23 = m[9], m24 = m[13], m31 = m[2], m32 = m[6], m33 = m[10], m34 = m[14], m41 = m[3], m42 = m[7], m43 = m[11], m44 = m[15];
              for (var i = 0; i < vin.length - 2; i += 3) {
                var x = vin.asGetNumericProperty(i), y = vin.asGetNumericProperty(i + 1), z = vin.asGetNumericProperty(i + 2);
                vout.push(m11 * x + m12 * y + m13 * z + m14);
                vout.push(m21 * x + m22 * y + m23 * z + m24);
                vout.push(m31 * x + m32 * y + m33 * z + m34);
              }
            },
            transpose: function transpose() {
              var m = this._matrix;
              var tmp;
              tmp = m[1];
              m[1] = m[4];
              m[4] = tmp;
              tmp = m[2];
              m[2] = m[8];
              m[5] = tmp;
              tmp = m[3];
              m[3] = m[12];
              m[12] = tmp;
              tmp = m[6];
              m[6] = m[9];
              m[9] = tmp;
              tmp = m[7];
              m[7] = m[13];
              m[13] = tmp;
              tmp = m[11];
              m[11] = m[14];
              m[14] = tmp;
            },
            pointAt: function pointAt(pos, at, up) {
              notImplemented('Matrix3D.pointAt');
            },
            interpolateTo: function interpolateTo(toMat, percent) {
              notImplemented('Matrix3D.interpolateTo');
            },
            copyFrom: function copyFrom(sourceMatrix3D) {
              this._matrix.set(sourceMatrix3D._matrix);
            },
            copyRawDataTo: function copyRawDataTo(vector, index, transpose) {
              var m = this._matrix;
              if (transpose) {
                for (var i = 0, j = index | 0; i < 16; i++, j++) {
                  vector.asSetNumericProperty(j, m[transposeTransform[i]]);
                }
              } else {
                for (var i = 0, j = index | 0; i < 16; i++, j++) {
                  vector.asSetNumericProperty(j, m[i]);
                }
              }
            },
            copyRawDataFrom: function copyRawDataFrom(vector, index, transpose) {
              var m = this._matrix;
              if (transpose) {
                for (var i = 0, j = index | 0; i < 16; i++, j++) {
                  m[transposeTransform[i]] = vector.asGetNumericProperty(j) || 0;
                }
              } else {
                for (var i = 0, j = index | 0; i < 16; i++, j++) {
                  m[i] = vector.asGetNumericProperty(j) || 0;
                }
              }
            },
            copyRowTo: function copyRowTo(row, vector3D) {
              var offset = row | 0;
              var m = this._matrix;
              vector3D.x = m[offset];
              vector3D.y = m[offset + 4];
              vector3D.z = m[offset + 8];
              vector3D.w = m[offset + 12];
            },
            copyColumnTo: function copyColumnTo(column, vector3D) {
              var offset = column << 2;
              var m = this._matrix;
              vector3D.x = m[offset];
              vector3D.y = m[offset + 1];
              vector3D.z = m[offset + 2];
              vector3D.w = m[offset + 3];
            },
            copyRowFrom: function copyRowFrom(row, vector3D) {
              var offset = row | 0;
              var m = this._matrix;
              m[offset] = vector3D.x;
              m[offset + 4] = vector3D.y;
              m[offset + 8] = vector3D.z;
              m[offset + 12] = vector3D.w;
            },
            copyColumnFrom: function copyColumnFrom(column, vector3D) {
              var offset = column << 2;
              var m = this._matrix;
              m[offset] = vector3D.x;
              m[offset + 1] = vector3D.y;
              m[offset + 2] = vector3D.z;
              m[offset + 3] = vector3D.w;
            },
            rawData: {
              get: function rawData() {
                var result = new Float64Vector();
                this.copyRawDataTo(result, 0, false);
                return result;
              },
              set: function rawData(v) {
                this.copyRawDataFrom(v, 0, false);
              }
            },
            position: {
              get: function position() {
                var m = this._matrix;
                return new flash.geom.Vector3D(m[12], m[13], m[14]);
              },
              set: function position(pos) {
                var m = this._matrix;
                m[12] = pos.x;
                m[13] = pos.y;
                m[14] = pos.z;
              }
            },
            determinant: {
              get: function determinant() {
                var m = this._matrix;
                var m11 = m[0], m12 = m[4], m13 = m[8], m14 = m[12], m21 = m[1], m22 = m[5], m23 = m[9], m24 = m[13], m31 = m[2], m32 = m[6], m33 = m[10], m34 = m[14], m41 = m[3], m42 = m[7], m43 = m[11], m44 = m[15];
                var d;
                d = m11 * (m22 * (m33 * m44 - m43 * m34) - m32 * (m23 * m44 - m43 * m24) + m42 * (m23 * m34 - m33 * m24)) - m21 * (m12 * (m33 * m44 - m43 * m34) - m32 * (m13 * m44 - m43 * m14) + m42 * (m13 * m34 - m33 * m14)) + m31 * (m12 * (m23 * m44 - m43 * m24) - m22 * (m13 * m44 - m43 * m14) + m42 * (m13 * m24 - m23 * m14)) - m41 * (m12 * (m23 * m34 - m33 * m24) - m22 * (m13 * m34 - m33 * m14) + m32 * (m13 * m24 - m23 * m14));
                return d;
              }
            }
          }
        },
        script: {
          instance: Glue.ALL
        }
      }
    };
  }.call(this);
var PointDefinition = function () {
    return {
      __class__: 'flash.geom.Point',
      __glue__: {
        script: {
          static: Glue.ALL,
          instance: Glue.ALL
        }
      }
    };
  }.call(this);
var RectangleDefinition = function () {
    return {
      __class__: 'flash.geom.Rectangle',
      __glue__: {
        script: {
          instance: Glue.ALL
        }
      }
    };
  }.call(this);
var TransformDefinition = function () {
    var def = {
        __class__: 'flash.geom.Transform',
        get colorTransform() {
          var cxform = this._target._cxform;
          if (cxform) {
            return new flash.geom.ColorTransform(cxform.redMultiplier / 256, cxform.greenMultiplier / 256, cxform.blueMultiplier / 256, cxform.alphaMultiplier / 256, cxform.redOffset, cxform.greenOffset, cxform.blueOffset, cxform.alphaOffset);
          } else {
            return new flash.geom.ColorTransform();
          }
        },
        set colorTransform(val) {
          var CTClass = avm2.systemDomain.getClass('flash.geom.ColorTransform');
          if (!CTClass.isInstanceOf(val)) {
            throwError('TypeError', Errors.CheckTypeFailedError, val, 'flash.geom.ColorTransform');
          }
          this._target._cxform = {
            redMultiplier: val.redMultiplier * 256,
            greenMultiplier: val.greenMultiplier * 256,
            blueMultiplier: val.blueMultiplier * 256,
            alphaMultiplier: val.alphaMultiplier * 256,
            redOffset: val.redOffset,
            greenOffset: val.greenOffset,
            blueOffset: val.blueOffset,
            alphaOffset: val.alphaOffset
          };
          this._target._invalidate();
        },
        get concatenatedColorTransform() {
          var cxform = this.colorTransform;
          cxform.concat(this._target.parent.transform.concatenatedColorTransform);
          return cxform;
        },
        get concatenatedMatrix() {
          if (this._target._current3DTransform) {
            return null;
          }
          var m = this._target._getConcatenatedTransform(null, false);
          return new flash.geom.Matrix(m.a, m.b, m.c, m.d, m.tx / 20, m.ty / 20);
        },
        get matrix() {
          if (this._target._current3DTransform) {
            return null;
          }
          var m = this._target._currentTransform;
          return new flash.geom.Matrix(m.a, m.b, m.c, m.d, m.tx / 20, m.ty / 20);
        },
        set matrix(val) {
          if (!flash.geom.Matrix.class.isInstanceOf(val)) {
            throwError('TypeError', Errors.CheckTypeFailedError, val, 'flash.geom.Matrix');
          }
          var target = this._target;
          target._invalidate();
          target._setTransformMatrix(val, true);
          target._current3DTransform = null;
          target._animated = false;
        },
        get matrix3D() {
          var m = this._target._current3DTransform;
          return m && m.clone();
        },
        set matrix3D(val) {
          var Matrix3DClass = avm2.systemDomain.getClass('flash.geom.Matrix3D');
          if (!Matrix3DClass.isInstanceOf(val)) {
            throwError('TypeError', Errors.CheckTypeFailedError, val, 'flash.geom.Matrix3D');
          }
          var raw = val.rawData;
          this.matrix = new flash.geom.Matrix(raw.asGetPublicProperty(0), raw.asGetPublicProperty(1), raw.asGetPublicProperty(4), raw.asGetPublicProperty(5), raw.asGetPublicProperty(12), raw.asGetPublicProperty(13));
          this._target._current3DTransform = val;
        },
        ctor: function (target) {
          this._target = target;
        }
      };
    var desc = Object.getOwnPropertyDescriptor;
    def.__glue__ = {
      native: {
        instance: {
          colorTransform: desc(def, 'colorTransform'),
          concatenatedColorTransform: desc(def, 'concatenatedColorTransform'),
          concatenatedMatrix: desc(def, 'concatenatedMatrix'),
          matrix: desc(def, 'matrix'),
          matrix3D: desc(def, 'matrix3D'),
          ctor: def.ctor
        }
      }
    };
    return def;
  }.call(this);
var Vector3DDefinition = function () {
    return {
      __class__: 'flash.geom.Vector3D',
      initialize: function () {
      },
      __glue__: {
        script: {
          instance: Glue.ALL
        }
      }
    };
  }.call(this);
{
  var ID3InfoDefinition = function () {
      return {
        __glue__: {
          script: {
            instance: {
              songName: 'public songName',
              genre: 'public genre',
              artist: 'public artist',
              track: 'public track',
              album: 'public album',
              year: 'public year',
              comment: 'public comment'
            }
          }
        }
      };
    }.call(this);
}
var MicrophoneDefinition = function () {
    return {
      __class__: 'flash.media.Microphone',
      initialize: function () {
      },
      __glue__: {
        native: {
          static: {
            getMicrophone: function getMicrophone(index) {
              notImplemented('Microphone.getMicrophone');
            },
            getEnhancedMicrophone: function getEnhancedMicrophone(index) {
              notImplemented('Microphone.getEnhancedMicrophone');
            },
            names: {
              get: function names() {
                notImplemented('Microphone.names');
              }
            },
            isSupported: {
              get: function isSupported() {
                notImplemented('Microphone.isSupported');
              }
            }
          },
          instance: {
            setSilenceLevel: function setSilenceLevel(silenceLevel, timeout) {
              notImplemented('Microphone.setSilenceLevel');
            },
            setUseEchoSuppression: function setUseEchoSuppression(useEchoSuppression) {
              notImplemented('Microphone.setUseEchoSuppression');
            },
            setLoopBack: function setLoopBack(state) {
              notImplemented('Microphone.setLoopBack');
            },
            gain: {
              set: function gain(gain) {
                notImplemented('Microphone.gain');
                this._gain = gain;
              },
              get: function gain() {
                notImplemented('Microphone.gain');
                return this._gain;
              }
            },
            rate: {
              set: function rate(rate) {
                notImplemented('Microphone.rate');
                this._rate = rate;
              },
              get: function rate() {
                notImplemented('Microphone.rate');
                return this._rate;
              }
            },
            codec: {
              set: function codec(codec) {
                notImplemented('Microphone.codec');
                this._codec = codec;
              },
              get: function codec() {
                notImplemented('Microphone.codec');
                return this._codec;
              }
            },
            framesPerPacket: {
              get: function framesPerPacket() {
                notImplemented('Microphone.framesPerPacket');
                return this._framesPerPacket;
              },
              set: function framesPerPacket(frames) {
                notImplemented('Microphone.framesPerPacket');
                this._framesPerPacket = frames;
              }
            },
            encodeQuality: {
              get: function encodeQuality() {
                notImplemented('Microphone.encodeQuality');
                return this._encodeQuality;
              },
              set: function encodeQuality(quality) {
                notImplemented('Microphone.encodeQuality');
                this._encodeQuality = quality;
              }
            },
            noiseSuppressionLevel: {
              get: function noiseSuppressionLevel() {
                notImplemented('Microphone.noiseSuppressionLevel');
                return this._noiseSuppressionLevel;
              },
              set: function noiseSuppressionLevel(level) {
                notImplemented('Microphone.noiseSuppressionLevel');
                this._noiseSuppressionLevel = level;
              }
            },
            enableVAD: {
              get: function enableVAD() {
                notImplemented('Microphone.enableVAD');
                return this._enableVAD;
              },
              set: function enableVAD(enable) {
                notImplemented('Microphone.enableVAD');
                this._enableVAD = enable;
              }
            },
            activityLevel: {
              get: function activityLevel() {
                notImplemented('Microphone.activityLevel');
                return this._activityLevel;
              }
            },
            index: {
              get: function index() {
                notImplemented('Microphone.index');
                return this._index;
              }
            },
            muted: {
              get: function muted() {
                notImplemented('Microphone.muted');
                return this._muted;
              }
            },
            name: {
              get: function name() {
                notImplemented('Microphone.name');
                return this._name;
              }
            },
            silenceLevel: {
              get: function silenceLevel() {
                notImplemented('Microphone.silenceLevel');
                return this._silenceLevel;
              }
            },
            silenceTimeout: {
              get: function silenceTimeout() {
                notImplemented('Microphone.silenceTimeout');
                return this._silenceTimeout;
              }
            },
            useEchoSuppression: {
              get: function useEchoSuppression() {
                notImplemented('Microphone.useEchoSuppression');
                return this._useEchoSuppression;
              }
            },
            soundTransform: {
              get: function soundTransform() {
                notImplemented('Microphone.soundTransform');
                return this._soundTransform;
              },
              set: function soundTransform(sndTransform) {
                notImplemented('Microphone.soundTransform');
                this._soundTransform = sndTransform;
              }
            },
            enhancedOptions: {
              get: function enhancedOptions() {
                notImplemented('Microphone.enhancedOptions');
                return this._enhancedOptions;
              },
              set: function enhancedOptions(options) {
                notImplemented('Microphone.enhancedOptions');
                this._enhancedOptions = options;
              }
            }
          }
        },
        script: {
          instance: Glue.ALL
        }
      }
    };
  }.call(this);
var PLAY_USING_AUDIO_TAG = true;
var SoundDefinition = function () {
    function getAudioDescription(soundData, onComplete) {
      var audioElement = document.createElement('audio');
      if (!audioElement.canPlayType(soundData.mimeType)) {
        onComplete({
          duration: 0
        });
        return;
      }
      audioElement.preload = 'metadata';
      var blob = new Blob([
          soundData.data
        ], {
          type: soundData.mimeType
        });
      audioElement.src = URL.createObjectURL(blob);
      audioElement.load();
      audioElement.addEventListener('loadedmetadata', function () {
        onComplete({
          duration: this.duration * 1000
        });
      });
    }
    var def = {
        initialize: function initialize() {
          this._playQueue = [];
          this._url = null;
          this._length = 0;
          this._bytesTotal = 0;
          this._bytesLoaded = 0;
          this._id3 = new flash.media.ID3Info();
          var s = this.symbol;
          if (s) {
            var soundData = {};
            if (s.pcm) {
              soundData.sampleRate = s.sampleRate;
              soundData.channels = s.channels;
              soundData.pcm = s.pcm;
              soundData.end = s.pcm.length;
            }
            soundData.completed = true;
            if (s.packaged) {
              soundData.data = s.packaged.data.buffer;
              soundData.mimeType = s.packaged.mimeType;
            }
            var _this = this;
            getAudioDescription(soundData, function (description) {
              _this._length = description.duration;
            });
            this._soundData = soundData;
          }
          TelemetryService.reportTelemetry({
            topic: 'feature',
            feature: SOUND_FEATURE
          });
        },
        close: function close() {
          somewhatImplemented('Sound.close');
        },
        extract: function extract(target, length, startPosition) {
          notImplemented('Sound.extract');
        },
        _load: function _load(request, checkPolicyFile, bufferTime) {
          if (!request) {
            return;
          }
          var _this = this;
          var stream = this._stream = new flash.net.URLStream();
          var ByteArrayClass = avm2.systemDomain.getClass('flash.utils.ByteArray');
          var data = ByteArrayClass.createInstance();
          var dataPosition = 0;
          var mp3DecodingSession = null;
          var soundData = {
              completed: false
            };
          stream._addEventListener('progress', function (event) {
            _this._bytesLoaded = event[Multiname.getPublicQualifiedName('bytesLoaded')];
            _this._bytesTotal = event[Multiname.getPublicQualifiedName('bytesTotal')];
            if (!PLAY_USING_AUDIO_TAG && !mp3DecodingSession) {
              mp3DecodingSession = decodeMP3(soundData, function (duration, final) {
                if (_this._length === 0) {
                  _this._soundData = soundData;
                  _this._playQueue.forEach(function (item) {
                    item.channel._playSoundDataViaChannel(soundData, item.startTime);
                  });
                }
                _this._length = final ? duration * 1000 : Math.max(duration, mp3DecodingSession.estimateDuration(_this._bytesTotal)) * 1000;
              });
            }
            var bytesAvailable = stream.bytesAvailable;
            stream.readBytes(data, dataPosition, bytesAvailable);
            if (mp3DecodingSession) {
              mp3DecodingSession.pushData(new Uint8Array(data.a, dataPosition, bytesAvailable));
            }
            dataPosition += bytesAvailable;
            _this._dispatchEvent(event);
          });
          stream._addEventListener('complete', function (event) {
            _this._dispatchEvent(event);
            soundData.data = data.a;
            soundData.mimeType = 'audio/mpeg';
            soundData.completed = true;
            if (PLAY_USING_AUDIO_TAG) {
              _this._soundData = soundData;
              getAudioDescription(soundData, function (description) {
                _this._length = description.duration;
              });
              _this._playQueue.forEach(function (item) {
                item.channel._playSoundDataViaAudio(soundData, item.startTime);
              });
            }
            if (mp3DecodingSession) {
              mp3DecodingSession.close();
            }
          });
          stream.load(request);
        },
        loadCompressedDataFromByteArray: function loadCompressedDataFromByteArray(bytes, bytesLength) {
          notImplemented('Sound#loadCompressedDataFromByteArray');
        },
        loadPCMFromByteArray: function loadPCMFromByteArray(bytes, samples, format, stereo, sampleRate) {
          notImplemented('Sound#loadPCMFromByteArray');
        },
        play: function play(startTime, loops, soundTransform) {
          startTime = startTime || 0;
          loops = loops || 0;
          var channel = new flash.media.SoundChannel();
          channel._sound = this;
          channel._soundTransform = isNullOrUndefined(soundTransform) ? new flash.media.SoundTransform() : soundTransform;
          this._playQueue.push({
            channel: channel,
            startTime: startTime
          });
          if (this._soundData) {
            if (PLAY_USING_AUDIO_TAG)
              channel._playSoundDataViaAudio(this._soundData, startTime, loops);
            else
              channel._playSoundDataViaChannel(this._soundData, startTime, loops);
          }
          return channel;
        },
        get bytesLoaded() {
          return this._bytesLoaded;
        },
        get bytesTotal() {
          return this._bytesTotal;
        },
        get id3() {
          return this._id3;
        },
        get isBuffering() {
          notImplemented('Sound#isBuffering');
        },
        get isURLInaccessible() {
          notImplemented('Sound#isURLInaccessible');
        },
        get length() {
          return this._length;
        },
        get url() {
          return this._url;
        }
      };
    function decodeMP3(soundData, ondurationchanged) {
      var currentSize = 8000;
      var pcm = new Float32Array(currentSize);
      var position = 0;
      var lastTimeRatio = 0;
      var durationEstimationData = {
          estimateBitRate: true,
          bitRateSum: 0,
          bitRateCount: 0,
          metadataSize: 0,
          averageBitRate: 0
        };
      var mp3DecoderSession = new MP3DecoderSession();
      mp3DecoderSession.onframedata = function (frame, channels, sampleRate, bitRate) {
        if (durationEstimationData.estimateBitRate) {
          var FramesToEstimate = 200;
          if (durationEstimationData.bitRateCount < FramesToEstimate) {
            durationEstimationData.bitRateSum += bitRate;
            durationEstimationData.bitRateCount++;
          } else {
            durationEstimationData.estimateBitRate = false;
          }
          this.averageBitRate = durationEstimationData.bitRateSum / durationEstimationData.bitRateCount;
        }
        if (frame.length === 0)
          return;
        if (!position) {
          soundData.sampleRate = sampleRate, soundData.channels = channels;
          soundData.pcm = pcm;
        }
        if (position + frame.length >= currentSize) {
          do {
            currentSize *= 2;
          } while (position + frame.length >= currentSize);
          var newPcm = new Float32Array(currentSize);
          newPcm.set(pcm);
          pcm = soundData.pcm = newPcm;
        }
        pcm.set(frame, position);
        soundData.end = position += frame.length;
        lastTimeRatio = 1 / soundData.sampleRate / soundData.channels;
        ondurationchanged(position * lastTimeRatio, false);
      };
      mp3DecoderSession.onid3tag = function (data) {
        durationEstimationData.metadataSize += data.length;
      }, mp3DecoderSession.onclosed = function () {
        ondurationchanged(position * lastTimeRatio, true);
      };
      var completed = false;
      return {
        pushData: function (data) {
          mp3DecoderSession.pushAsync(data);
        },
        estimateDuration: function (fileSize) {
          return Math.max(0, (fileSize - durationEstimationData.metadataSize) * 8 / durationEstimationData.averageBitRate);
        },
        close: function () {
          mp3DecoderSession.close();
        }
      };
    }
    var desc = Object.getOwnPropertyDescriptor;
    def.__glue__ = {
      native: {
        instance: {
          close: def.close,
          extract: def.extract,
          _load: def._load,
          loadCompressedDataFromByteArray: def.loadCompressedDataFromByteArray,
          loadPCMFromByteArray: def.loadPCMFromByteArray,
          play: def.play,
          bytesLoaded: desc(def, 'bytesLoaded'),
          bytesTotal: desc(def, 'bytesTotal'),
          id3: desc(def, 'id3'),
          isBuffering: desc(def, 'isBuffering'),
          isURLInaccessible: desc(def, 'isURLInaccessible'),
          length: desc(def, 'length'),
          url: desc(def, 'url')
        }
      }
    };
    return def;
  }.call(this);
var SoundChannelDefinition = function () {
    return {
      initialize: function () {
        this._element = null;
        this._position = 0;
        this._leftPeak = 0;
        this._rightPeak = 0;
        this._pcmData = null;
        this._soundTransform = new flash.media.SoundTransform();
        this._soundMixerClass = avm2.systemDomain.getClass('flash.media.SoundMixer');
        var s = this.symbol;
        if (s) {
          this._element = s.element || null;
        }
        if (this._element) {
          this._registerWithSoundMixer();
        }
      },
      _registerWithSoundMixer: function () {
        this._soundMixerClass.native.static._registerChannel(this);
      },
      _unregisterWithSoundMixer: function () {
        this._soundMixerClass.native.static._unregisterChannel(this);
      },
      _applySoundTransform: function () {
        var volume = this._soundTransform._volume;
        if (this._soundMixerClass._soundTransform) {
          volume *= this._soundMixerClass._soundTransform._volume;
        }
        volume *= this._soundMixerClass.native.static._getMasterVolume();
        if (this._element) {
          this._element.volume = clamp(volume, 0, 1);
        }
        if (this._audioChannel) {
        }
      },
      _playSoundDataViaChannel: function (soundData, startTime, loops) {
        this._registerWithSoundMixer();
        var self = this;
        var startPosition = Math.round(startTime / 1000 * soundData.sampleRate) * soundData.channels;
        var position = startPosition;
        this._position = startTime;
        this._audioChannel = createAudioChannel(soundData.sampleRate, soundData.channels);
        this._audioChannel.ondatarequested = function (e) {
          var end = soundData.end;
          if (position >= end && soundData.completed) {
            self._unregisterWithSoundMixer();
            self._audioChannel.stop();
            self._dispatchEvent(new flash.events.Event('soundComplete', false, false));
            return;
          }
          var left = e.count;
          var data = e.data;
          var source = soundData.pcm;
          do {
            var count = Math.min(end - position, left);
            for (var j = 0; j < count; j++) {
              data[j] = source[position++];
            }
            left -= count;
            if (position >= end) {
              if (!loops)
                break;
              loops--;
              position = startPosition;
            }
          } while (left > 0);
          self._position = position / soundData.sampleRate / soundData.channels * 1000;
        };
        this._audioChannel.start();
        this._applySoundTransform();
      },
      _playSoundDataViaAudio: function (soundData, startTime, loops) {
        if (!soundData.mimeType)
          return;
        this._registerWithSoundMixer();
        this._position = startTime;
        var self = this;
        var lastCurrentTime = 0;
        var element = document.createElement('audio');
        if (!element.canPlayType(soundData.mimeType)) {
          console.error('ERROR: "' + soundData.mimeType + '" ' + 'type playback is not supported by the browser');
          return;
        }
        element.preload = 'metadata';
        element.loop = loops > 0;
        var blob = new Blob([
            soundData.data
          ], {
            type: soundData.mimeType
          });
        element.src = URL.createObjectURL(blob);
        element.addEventListener('loadeddata', function loaded() {
          element.currentTime = startTime / 1000;
          element.play();
        });
        element.addEventListener('timeupdate', function timeupdate() {
          var currentTime = element.currentTime;
          if (loops && lastCurrentTime > currentTime) {
            --loops;
            if (!loops)
              element.loop = false;
            if (currentTime < startTime / 1000)
              element.currentTime = startTime / 1000;
          }
          self._position = (lastCurrentTime = currentTime) * 1000;
        });
        element.addEventListener('ended', function ended() {
          self._unregisterWithSoundMixer();
          self._dispatchEvent(new flash.events.Event('soundComplete', false, false));
          self._element = null;
        });
        this._element = element;
        this._applySoundTransform();
      },
      __glue__: {
        native: {
          static: {},
          instance: {
            stop: function stop() {
              if (this._element) {
                this._unregisterWithSoundMixer();
                this._element.pause();
              }
              if (this._audioChannel) {
                this._unregisterWithSoundMixer();
                this._audioChannel.stop();
              }
            },
            'position': {
              get: function position() {
                return this._position;
              }
            },
            'leftPeak': {
              get: function leftPeak() {
                return this._leftPeak;
              }
            },
            'rightPeak': {
              get: function rightPeak() {
                return this.rightPeak;
              }
            },
            'soundTransform': {
              get: function soundTransform() {
                somewhatImplemented('SoundChannel.soundTransform');
                return new flash.media.SoundTransform(this._soundTransform._volume, this._soundTransform.pan);
              },
              set: function soundTransform(soundTransform) {
                somewhatImplemented('SoundChannel.soundTransform');
                this._soundTransform = isNullOrUndefined(soundTransform) ? new flash.media.SoundTransform() : soundTransform;
                this._applySoundTransform();
              }
            }
          }
        },
        script: {
          instance: scriptProperties('public', [
            'stop'
          ])
        }
      }
    };
  }.call(this);
function createAudioChannel(sampleRate, channels) {
  if (WebAudioChannel.isSupported)
    return new WebAudioChannel(sampleRate, channels);
  else
    error('PCM data playback is not supported by the browser');
}
function AudioResampler(sourceRate, targetRate) {
  this.sourceRate = sourceRate;
  this.targetRate = targetRate;
  this.tail = [];
  this.sourceOffset = 0;
}
AudioResampler.prototype = {
  ondatarequested: function (e) {
  },
  getData: function (channelsData, count) {
    var k = this.sourceRate / this.targetRate;
    var offset = this.sourceOffset;
    var needed = Math.ceil((count - 1) * k + offset) + 1;
    var sourceData = [];
    for (var channel = 0; channel < channelsData.length; channel++)
      sourceData.push(new Float32Array(needed));
    var e = {
        data: sourceData,
        count: needed
      };
    this.ondatarequested(e);
    for (var channel = 0; channel < channelsData.length; channel++) {
      var data = channelsData[channel];
      var source = sourceData[channel];
      for (var j = 0; j < count; j++) {
        var i = j * k + offset;
        var i1 = i | 0, i2 = Math.ceil(i) | 0;
        var source_i1 = i1 < 0 ? this.tail[channel] : source[i1];
        if (i1 === i2) {
          data[j] = source_i1;
        } else {
          var alpha = i - i1;
          data[j] = source_i1 * (1 - alpha) + source[i2] * alpha;
        }
      }
      this.tail[channel] = source[needed - 1];
    }
    this.sourceOffset = (count - 1) * k + offset - (needed - 1);
  }
};
function WebAudioChannel(sampleRate, channels) {
  var context = WebAudioChannel.context;
  if (!context) {
    if (typeof AudioContext !== 'undefined')
      context = new AudioContext();
    else
      context = new webkitAudioContext();
    WebAudioChannel.context = context;
  }
  this.context = context;
  this.contextSampleRate = context.sampleRate || 44100;
  this.channels = channels;
  this.sampleRate = sampleRate;
  if (this.contextSampleRate != sampleRate) {
    this.resampler = new AudioResampler(sampleRate, this.contextSampleRate);
    this.resampler.ondatarequested = function (e) {
      this.requestData(e.data, e.count);
    }.bind(this);
  }
}
WebAudioChannel.prototype = {
  start: function () {
    var source = this.context.createScriptProcessor ? this.context.createScriptProcessor(2048, 0, this.channels) : this.context.createJavaScriptNode(2048, 0, this.channels);
    var self = this;
    source.onaudioprocess = function (e) {
      var channelsData = [];
      for (var i = 0; i < self.channels; i++)
        channelsData.push(e.outputBuffer.getChannelData(i));
      var count = channelsData[0].length;
      if (self.resampler) {
        self.resampler.getData(channelsData, count);
      } else {
        var e = {
            data: channelsData,
            count: count
          };
        self.requestData(channelsData, count);
      }
    };
    source.connect(this.context.destination);
    this.source = source;
  },
  stop: function () {
    this.source.disconnect(this.context.destination);
  },
  requestData: function (channelsData, count) {
    var channels = this.channels;
    var buffer = new Float32Array(count * channels);
    var e = {
        data: buffer,
        count: buffer.length
      };
    this.ondatarequested(e);
    for (var j = 0, p = 0; j < count; j++) {
      for (var i = 0; i < channels; i++)
        channelsData[i][j] = buffer[p++];
    }
  }
};
WebAudioChannel.isSupported = function () {
  return typeof AudioContext !== 'undefined' || typeof webkitAudioContext != 'undefined';
}();
var SoundMixerDefinition = function () {
    var masterVolume = 1;
    var registeredChannels = [];
    return {
      __class__: 'flash.media.SoundMixer',
      initialize: function () {
      },
      __glue__: {
        native: {
          static: {
            _registerChannel: function _registerChannel(channel) {
              registeredChannels.push(channel);
            },
            _unregisterChannel: function _unregisterChannel(channel) {
              var index = registeredChannels.indexOf(channel);
              if (index >= 0)
                registeredChannels.splice(index, 1);
            },
            _getMasterVolume: function _getMasterVolume() {
              return masterVolume;
            },
            _setMasterVolume: function _setMasterVolume(volume) {
              masterVolume = volume;
              registeredChannels.forEach(function (channel) {
                channel._applySoundTransform();
              });
            },
            stopAll: function stopAll() {
              registeredChannels.forEach(function (channel) {
                channel.stop();
              });
              registeredChannels = [];
            },
            computeSpectrum: function computeSpectrum(outputArray, FFTMode, stretchFactor) {
              somewhatImplemented('SoundMixer.computeSpectrum');
              var data = new Float32Array(1024);
              for (var i = 0; i < 1024; i++) {
                data[i] = Math.random();
              }
              outputArray.writeRawBytes(data);
              outputArray.position = 0;
            },
            areSoundsInaccessible: function areSoundsInaccessible() {
              notImplemented('SoundMixer.areSoundsInaccessible');
            },
            bufferTime: {
              get: function bufferTime() {
                notImplemented('SoundMixer.bufferTime');
              },
              set: function bufferTime(pA) {
                notImplemented('SoundMixer.bufferTime');
              }
            },
            soundTransform: {
              get: function soundTransform() {
                somewhatImplemented('SoundMixer.soundTransform');
                return isNullOrUndefined(this._soundTransform) ? new flash.media.SoundTransform() : new flash.media.SoundTransform(this._soundTransform._volume, this._soundTransform.pan);
              },
              set: function soundTransform(soundTransform) {
                somewhatImplemented('SoundMixer.soundTransform');
                this._soundTransform = isNullOrUndefined(soundTransform) ? new flash.media.SoundTransform() : soundTransform;
                registeredChannels.forEach(function (channel) {
                  channel._applySoundTransform();
                });
              }
            },
            audioPlaybackMode: {
              get: function audioPlaybackMode() {
                notImplemented('SoundMixer.audioPlaybackMode');
              },
              set: function audioPlaybackMode(pA) {
                notImplemented('SoundMixer.audioPlaybackMode');
              }
            },
            useSpeakerphoneForVoice: {
              get: function useSpeakerphoneForVoice() {
                notImplemented('SoundMixer.useSpeakerphoneForVoice');
              },
              set: function useSpeakerphoneForVoice(pA) {
                notImplemented('SoundMixer.useSpeakerphoneForVoice');
              }
            }
          },
          instance: {}
        }
      }
    };
  }.call(this);
var SoundTransformDefinition = function () {
    return {
      __class__: 'flash.media.SoundTransform',
      initialize: function () {
      },
      _updateTransform: function () {
        somewhatImplemented('SoundTransform._updateTransform');
      },
      __glue__: {
        native: {
          static: {},
          instance: {
            volume: {
              get: function volume() {
                return this._volume;
              },
              set: function volume(volume) {
                this._volume = volume;
                this._updateTransform();
              }
            },
            leftToLeft: {
              get: function leftToLeft() {
                return this._leftToLeft;
              },
              set: function leftToLeft(leftToLeft) {
                this._leftToLeft = leftToLeft;
                this._updateTransform();
              }
            },
            leftToRight: {
              get: function leftToRight() {
                return this._leftToRight;
              },
              set: function leftToRight(leftToRight) {
                this._leftToRight = leftToRight;
                this._updateTransform();
              }
            },
            rightToRight: {
              get: function rightToRight() {
                return this._rightToRight;
              },
              set: function rightToRight(rightToRight) {
                this._rightToRight = rightToRight;
                this._updateTransform();
              }
            },
            rightToLeft: {
              get: function rightToLeft() {
                return this._rightToLeft;
              },
              set: function rightToLeft(rightToLeft) {
                this._rightToLeft = rightToLeft;
                this._updateTransform();
              }
            }
          }
        },
        script: {
          instance: {
            pan: 'public pan'
          }
        }
      }
    };
  }.call(this);
var StageVideoDefinition = function () {
    return {
      __class__: 'flash.media.StageVideo',
      initialize: function () {
      },
      __glue__: {
        native: {
          static: {},
          instance: {
            attachNetStream: function attachNetStream(netStream) {
              notImplemented('StageVideo.attachNetStream');
            },
            attachCamera: function attachCamera(theCamera) {
              notImplemented('StageVideo.attachCamera');
            },
            viewPort: {
              get: function viewPort() {
                notImplemented('StageVideo.viewPort');
                return this._viewPort;
              },
              set: function viewPort(rect) {
                notImplemented('StageVideo.viewPort');
                this._viewPort = rect;
              }
            },
            pan: {
              set: function pan(point) {
                notImplemented('StageVideo.pan');
                this._pan = point;
              },
              get: function pan() {
                notImplemented('StageVideo.pan');
                return this._pan;
              }
            },
            zoom: {
              set: function zoom(point) {
                notImplemented('StageVideo.zoom');
                this._zoom = point;
              },
              get: function zoom() {
                notImplemented('StageVideo.zoom');
                return this._zoom;
              }
            },
            depth: {
              set: function depth(depth) {
                notImplemented('StageVideo.depth');
                this._depth = depth;
              },
              get: function depth() {
                notImplemented('StageVideo.depth');
                return this._depth;
              }
            },
            videoWidth: {
              get: function videoWidth() {
                notImplemented('StageVideo.videoWidth');
                return this._videoWidth;
              }
            },
            videoHeight: {
              get: function videoHeight() {
                notImplemented('StageVideo.videoHeight');
                return this._videoHeight;
              }
            },
            colorSpaces: {
              get: function colorSpaces() {
                notImplemented('StageVideo.colorSpaces');
                return this._colorSpaces;
              }
            }
          }
        }
      }
    };
  }.call(this);
var VideoDefinition = function () {
    function burnHole(ctx, x, y, width, height) {
      ctx.save();
      ctx.beginPath();
      ctx.rect(0, 0, width, height);
      ctx.clip();
      ctx.clearRect(0, 0, width, height);
      ctx.restore();
    }
    var def = {
        initialize: function initialize() {
          TelemetryService.reportTelemetry({
            topic: 'feature',
            feature: VIDEO_FEATURE
          });
        },
        attachNetStream: function (netStream) {
          if (this._netStream === netStream) {
            return;
          }
          if (this._netStream) {
            this._netStream._videoReady.then(function (element) {
              this._element = null;
              if (this._added) {
                element.remove();
                this._added = false;
              }
            }.bind(this));
          }
          this._netStream = netStream;
          if (!netStream) {
            return;
          }
          netStream._videoReady.then(function (element) {
            this._element = element;
            netStream._videoMetadataReady.then(function (url) {
              this._element.width = this._videoWidth = this._element.videoWidth;
              this._element.height = this._videoHeight = this._element.videoHeight;
              if (this.stage) {
                this.stage._invalid = true;
              }
            }.bind(this));
          }.bind(this));
        },
        ctor: function (width, height) {
          if (!width || width < 0)
            width = 320;
          if (!height || height < 0)
            height = 240;
          this._bbox = {
            xMin: 0,
            yMin: 0,
            xMax: width * 20,
            yMax: height * 20
          };
          this._initialWidth = this._videoWidth = width;
          this._initialHeight = this._videoHeight = height;
          this._netStream = null;
          this._element = null;
          this._added = false;
        },
        draw: function (ctx, ratio, ct, parentCtxs) {
          if (!this._element) {
            return;
          }
          if (!this._added && this._stage) {
            this._stage._domContainer.appendChild(this._element);
            this._added = true;
          }
          var width = this._initialWidth;
          var height = this._initialHeight;
          var matrix = this._getConcatenatedTransform(null, true);
          var scaleFactor = this.stage && this.stage._contentsScaleFactor || 1;
          var a = matrix.a / scaleFactor;
          var b = matrix.b / scaleFactor;
          var c = matrix.c / scaleFactor;
          var d = matrix.d / scaleFactor;
          var e = matrix.tx / 20 / scaleFactor;
          var f = matrix.ty / 20 / scaleFactor;
          if (width > 0 && height > 0) {
            burnHole(ctx, 0, 0, width, height);
            parentCtxs.forEach(function (ctx) {
              ctx.save();
              ctx.setTransform(a, b, c, d, e, f);
              burnHole(ctx, 0, 0, width, height);
              ctx.restore();
            });
          }
          var sx = width / this._videoWidth;
          var sy = height / this._videoHeight;
          var cssTransform = 'transform: matrix(' + sx * a + ',' + sx * b + ',' + sy * c + ',' + sy * d + ',' + e + ',' + f + ');';
          if (this._currentCssTransform !== cssTransform) {
            this._currentCssTransform = cssTransform;
            this._element.setAttribute('style', 'position: absolute; top:0; left:0; z-index: -100;transform-origin: 0px 0px 0;' + cssTransform + '-webkit-transform-origin: 0px 0px 0; -webkit-' + cssTransform);
          }
        }
      };
    def.__glue__ = {
      native: {
        instance: {
          attachNetStream: def.attachNetStream,
          ctor: def.ctor,
          smoothing: {
            get: function smoothing() {
              return this._smoothing;
            },
            set: function smoothing(value) {
              somewhatImplemented('Video.smoothing');
              this._smoothing = value;
            }
          },
          videoHeight: {
            get: function videoHeight() {
              return this._videoHeight;
            }
          },
          videoWidth: {
            get: function videoWidth() {
              return this._videoWidth;
            }
          }
        }
      }
    };
    return def;
  }.call(this);
{
  var FileFilterDefinition = function () {
      return {
        __class__: 'flash.net.FileFilter',
        initialize: function () {
          this._description = null;
          this._extension = null;
          this._macType = null;
        },
        __glue__: {
          native: {
            static: {},
            instance: {
              description: {
                get: function description() {
                  return this._description;
                },
                set: function description(value) {
                  this._description = value;
                }
              },
              extension: {
                get: function extension() {
                  return this._extension;
                },
                set: function extension(value) {
                  this._extension = value;
                }
              },
              macType: {
                get: function macType() {
                  return this._macType;
                },
                set: function macType(value) {
                  this._macType = value;
                }
              }
            }
          }
        }
      };
    }.call(this);
}
var LocalConnectionDefinition = function () {
    return {
      __class__: 'flash.net.LocalConnection',
      initialize: function () {
      },
      __glue__: {
        native: {
          static: {},
          instance: {
            close: function close() {
              notImplemented('LocalConnection.close');
            },
            connect: function connect(connectionName) {
              notImplemented('LocalConnection.connect');
            },
            send: function send(connectionName, methodName) {
              notImplemented('LocalConnection.send');
            },
            allowDomain: function allowDomain() {
              notImplemented('LocalConnection.allowDomain');
            },
            allowInsecureDomain: function allowInsecureDomain() {
              notImplemented('LocalConnection.allowInsecureDomain');
            },
            domain: {
              get: function domain() {
                somewhatImplemented('LocalConnection.domain');
                var url = FileLoadingService.resolveUrl('/');
                var m = /:\/\/(.+?)[:?#\/]/.exec(url);
                return m && m[1];
              }
            },
            client: {
              get: function client() {
                notImplemented('LocalConnection.client');
                return this._client;
              },
              set: function client(client) {
                notImplemented('LocalConnection.client');
                this._client = client;
              }
            },
            isPerUser: {
              get: function isPerUser() {
                notImplemented('LocalConnection.isPerUser');
                return this._isPerUser;
              },
              set: function isPerUser(newValue) {
                notImplemented('LocalConnection.isPerUser');
                this._isPerUser = newValue;
              }
            }
          }
        }
      }
    };
  }.call(this);
var NetConnectionDefinition = function () {
    var defaultObjectEncoding = 3;
    return {
      __class__: 'flash.net.NetConnection',
      initialize: function () {
        TelemetryService.reportTelemetry({
          topic: 'feature',
          feature: NETCONNECTION_FEATURE
        });
      },
      _invoke: function (index, args) {
        var simulated = false, result;
        switch (index) {
        case 2:
          simulated = true;
          break;
        }
        (simulated ? somewhatImplemented : notImplemented)('NetConnection._invoke (' + index + ')');
        return result;
      },
      __glue__: {
        native: {
          static: {
            defaultObjectEncoding: {
              get: function defaultObjectEncoding() {
                return defaultObjectEncoding;
              },
              set: function defaultObjectEncoding(version) {
                somewhatImplemented('NetConnection.defaultObjectEncoding');
                return defaultObjectEncoding;
              }
            }
          },
          instance: {
            ctor: function ctor() {
              this._uri = null;
              this._connected = false;
              this._client = null;
              this._proxyType = 'none';
              this._objectEncoding = defaultObjectEncoding;
            },
            connect: function connect(command) {
              var NetStatusEvent = flash.events.NetStatusEvent;
              somewhatImplemented('NetConnection.connect');
              this._uri = command;
              if (!command) {
                this._connected = true;
                this._dispatchEvent(new NetStatusEvent(NetStatusEvent.class.NET_STATUS, false, false, wrapJSObject({
                  level: 'status',
                  code: 'NetConnection.Connect.Success'
                })));
              } else {
                this._dispatchEvent(new NetStatusEvent(NetStatusEvent.class.NET_STATUS, false, false, wrapJSObject({
                  level: 'status',
                  code: 'NetConnection.Connect.Failed'
                })));
              }
            },
            call: function call(command, responder) {
              notImplemented('NetConnection.call');
            },
            connected: {
              get: function connected() {
                return this._connected;
              }
            },
            uri: {
              get: function uri() {
                return this._uri;
              }
            },
            client: {
              get: function client() {
                return this._client;
              },
              set: function client(object) {
                this._client = object;
              }
            },
            objectEncoding: {
              get: function objectEncoding() {
                return this._objectEncoding;
              },
              set: function objectEncoding(version) {
                somewhatImplemented('NetConnection.objectEncoding');
                this._objectEncoding = version;
              }
            },
            proxyType: {
              get: function proxyType() {
                return this._proxyType;
              },
              set: function proxyType(ptype) {
                notImplemented('NetConnection.proxyType');
                this._proxyType = ptype;
              }
            },
            connectedProxyType: {
              get: function connectedProxyType() {
                notImplemented('NetConnection.connectedProxyType');
                return this._connectedProxyType;
              }
            },
            usingTLS: {
              get: function usingTLS() {
                somewhatImplemented('NetConnection.usingTLS');
                return false;
              }
            },
            protocol: {
              get: function protocol() {
                notImplemented('NetConnection.protocol');
                return this._protocol;
              }
            },
            maxPeerConnections: {
              get: function maxPeerConnections() {
                notImplemented('NetConnection.maxPeerConnections');
                return this._maxPeerConnections;
              },
              set: function maxPeerConnections(maxPeers) {
                notImplemented('NetConnection.maxPeerConnections');
                this._maxPeerConnections = maxPeers;
              }
            },
            nearID: {
              get: function nearID() {
                notImplemented('NetConnection.nearID');
                return this._nearID;
              }
            },
            farID: {
              get: function farID() {
                notImplemented('NetConnection.farID');
                return this._farID;
              }
            },
            nearNonce: {
              get: function nearNonce() {
                notImplemented('NetConnection.nearNonce');
                return this._nearNonce;
              }
            },
            farNonce: {
              get: function farNonce() {
                notImplemented('NetConnection.farNonce');
                return this._farNonce;
              }
            },
            unconnectedPeerStreams: {
              get: function unconnectedPeerStreams() {
                notImplemented('NetConnection.unconnectedPeerStreams');
                return this._unconnectedPeerStreams;
              }
            },
            invoke: function invokeWithArgsArray(index) {
              return this._invoke(index, Array.prototype.slice.call(arguments, 1));
            },
            invokeWithArgsArray: function invokeWithArgsArray(index, p_arguments) {
              return this._invoke.call(this, index, p_arguments);
            }
          }
        }
      }
    };
  }.call(this);
var USE_MEDIASOURCE_API = false;
var NetStreamDefinition = function () {
    return {
      __class__: 'flash.net.NetStream',
      initialize: function () {
      },
      _invoke: function (index, args) {
        var simulated = false, result;
        var videoElement = this._videoElement;
        switch (index) {
        case 4:
          this._videoState.bufferTime = args[0];
          simulated = true;
          break;
        case 202:
          switch (args[1]) {
          case 'pause':
            simulated = true;
            if (videoElement) {
              if (args[3] !== false && !videoElement.paused) {
                videoElement.pause();
              } else if (args[3] !== true && videoElement.paused) {
                videoElement.play();
              }
              videoElement.currentTime = args[4] / 1000;
            }
            break;
          case 'seek':
            simulated = true;
            if (videoElement && !videoElement.paused) {
              videoElement.currentTime = args[3] / 1000;
            }
            break;
          }
          break;
        case 300:
          result = videoElement ? videoElement.currentTime : 0;
          simulated = true;
          break;
        case 302:
          result = this._videoState.bufferTime;
          simulated = true;
          break;
        case 303:
          result = videoElement ? videoElement.duration : 0;
          simulated = true;
          break;
        case 305:
          result = this._videoState.buffer === 'full' ? 100 : this._videoState.buffer === 'progress' ? 50 : 0;
          simulated = true;
          break;
        case 306:
          result = 100;
          simulated = true;
          break;
        }
        (simulated ? somewhatImplemented : notImplemented)('NetStream._invoke (' + index + ')');
        return result;
      },
      _createVideoElement: function (url) {
        function notifyPlayStart(e) {
          if (netStream._videoState.started) {
            return;
          }
          netStream._videoState.started = true;
          netStream._dispatchEvent(new NetStatusEvent(NetStatusEvent.class.NET_STATUS, false, false, wrapJSObject({
            code: 'NetStream.Play.Start',
            level: 'status'
          })));
        }
        function notifyPlayStop(e) {
          netStream._videoState.started = false;
          netStream._dispatchEvent(new NetStatusEvent(NetStatusEvent.class.NET_STATUS, false, false, wrapJSObject({
            code: 'NetStream.Play.Stop',
            level: 'status'
          })));
        }
        function notifyBufferFull(e) {
          netStream._videoState.buffer = 'full';
          netStream._dispatchEvent(new NetStatusEvent(NetStatusEvent.class.NET_STATUS, false, false, wrapJSObject({
            code: 'NetStream.Buffer.Full',
            level: 'status'
          })));
        }
        function notifyProgress(e) {
          netStream._videoState.buffer = 'progress';
        }
        function notifyBufferEmpty(e) {
          netStream._videoState.buffer = 'empty';
          netStream._dispatchEvent(new NetStatusEvent(NetStatusEvent.class.NET_STATUS, false, false, wrapJSObject({
            code: 'NetStream.Buffer.Empty',
            level: 'status'
          })));
        }
        function notifyError(e) {
          var code = e.target.error.code === 4 ? 'NetStream.Play.NoSupportedTrackFound' : e.target.error.code === 3 ? 'NetStream.Play.FileStructureInvalid' : 'NetStream.Play.StreamNotFound';
          netStream._dispatchEvent(new NetStatusEvent(NetStatusEvent.class.NET_STATUS, false, false, wrapJSObject({
            code: code,
            level: 'error'
          })));
        }
        function notifyMetadata(e) {
          netStream._videoMetadataReady.resolve({
            videoWidth: element.videoWidth,
            videoHeight: element.videoHeight
          });
          if (netStream._client) {
            var data = {};
            data.asSetPublicProperty('width', element.videoWidth);
            data.asSetPublicProperty('height', element.videoHeight);
            data.asSetPublicProperty('duration', element.duration);
            netStream._client.asCallPublicProperty('onMetaData', [
              data
            ]);
          }
        }
        var NetStatusEvent = flash.events.NetStatusEvent;
        var netStream = this;
        if (/\.mp4$/i.test(url) && /Intel Mac OS X.*?Firefox\/\d+/.test(window.navigator.userAgent)) {
          url = 'http://videos-cdn.mozilla.net/brand/Mozilla_2011_Story.webm';
        }
        var element = document.createElement('video');
        element.preload = 'metadata';
        element.src = url;
        element.addEventListener('play', notifyPlayStart);
        element.addEventListener('ended', notifyPlayStop);
        element.addEventListener('loadeddata', notifyBufferFull);
        element.addEventListener('progress', notifyProgress);
        element.addEventListener('waiting', notifyBufferEmpty);
        element.addEventListener('loadedmetadata', notifyMetadata);
        element.addEventListener('error', notifyError);
        element.play();
        this._videoElement = element;
        this._videoReady.resolve(element);
      },
      __glue__: {
        script: {
          instance: scriptProperties('public', [
            'appendBytes',
            'appendBytesAction'
          ])
        },
        native: {
          static: {},
          instance: {
            ctor: function ctor(connection, peerID) {
              somewhatImplemented('NetStream.ctor');
              this._contentTypeHint = null;
              this._mediaSource = null;
              this._checkPolicyFile = true;
              this._videoElement = null;
              var videoReadyResolve, videoReadyReject;
              this._videoReady = new Promise(function (resolve, reject) {
                videoReadyResolve = resolve;
                videoReadyReject = reject;
              });
              this._videoReady.resolve = videoReadyResolve;
              this._videoReady.reject = videoReadyReject;
              var videoMetadataReadyResolve, videoMetadataReadyReject;
              this._videoMetadataReady = new Promise(function (resolve, reject) {
                videoMetadataReadyResolve = resolve;
                videoMetadataReadyReject = reject;
              });
              this._videoMetadataReady.resolve = videoMetadataReadyResolve;
              this._videoMetadataReady.reject = videoMetadataReadyReject;
              this._videoState = {
                started: false,
                buffer: 'empty',
                bufferTime: 0.1
              };
            },
            onResult: function onResult(streamId) {
              notImplemented('NetStream.onResult');
            },
            dispose: function dispose() {
              notImplemented('NetStream.dispose');
            },
            play: function play(url) {
              var isMediaSourceEnabled = USE_MEDIASOURCE_API;
              if (isMediaSourceEnabled && typeof MediaSource === 'undefined') {
                console.warn('MediaSource API is not enabled, falling back to regular playback');
                isMediaSourceEnabled = false;
              }
              if (!isMediaSourceEnabled) {
                somewhatImplemented('NetStream.play');
                this._createVideoElement(FileLoadingService.resolveUrl(url));
                return;
              }
              var mediaSource = new MediaSource();
              mediaSource.addEventListener('sourceopen', function (e) {
                this._mediaSource = mediaSource;
              }.bind(this));
              mediaSource.addEventListener('sourceend', function (e) {
                this._mediaSource = null;
              }.bind(this));
              this._createVideoElement(window.URL.createObjectURL(mediaSource));
              if (!url) {
                return;
              }
              var request = new flash.net.URLRequest(url);
              request._checkPolicyFile = this._checkPolicyFile;
              var stream = new flash.net.URLStream();
              stream._addEventListener('httpStatus', function (e) {
                var responseHeaders = e.asGetPublicProperty('responseHeaders');
                var contentTypeHeader = responseHeaders.filter(function (h) {
                    return h.asGetPublicProperty('name') === 'Content-Type';
                  })[0];
                if (contentTypeHeader && contentTypeHeader.asGetPublicProperty('value') !== 'application/octet-stream') {
                  this._contentTypeHint = contentTypeHeader.asGetPublicProperty('value');
                }
              }.bind(this));
              stream._addEventListener('progress', function (e) {
                var available = stream.bytesAvailable;
                var ByteArrayClass = avm2.systemDomain.getClass('flash.utils.ByteArray');
                var data = ByteArrayClass.createInstance();
                stream.readBytes(data, 0, available);
                this.appendBytes(data);
              }.bind(this));
              stream._addEventListener('complete', function (e) {
                this.appendBytesAction('endSequence');
              }.bind(this));
              stream.load(request);
            },
            play2: function play2(param) {
              notImplemented('NetStream.play2');
            },
            invoke: function invoke(index) {
              return this._invoke(index, Array.prototype.slice.call(arguments, 1));
            },
            invokeWithArgsArray: function invokeWithArgsArray(index, p_arguments) {
              return this._invoke.call(this, index, p_arguments);
            },
            appendBytes: function appendBytes(bytes) {
              if (this._mediaSource) {
                if (!this._mediaSourceBuffer) {
                  this._mediaSourceBuffer = this._mediaSource.addSourceBuffer(this._contentTypeHint);
                }
                this._mediaSourceBuffer.appendBuffer(new Uint8Array(bytes.a, 0, bytes.length));
              }
              somewhatImplemented('NetStream.appendBytes');
            },
            appendBytesAction: function appendBytesAction(netStreamAppendBytesAction) {
              if (netStreamAppendBytesAction === 'endSequence' && this._mediaSource) {
                this._mediaSource.endOfStream();
              }
              somewhatImplemented('NetStream.appendBytesAction');
            },
            info: {
              get: function info() {
                notImplemented('NetStream.info');
                return this._info;
              }
            },
            multicastInfo: {
              get: function multicastInfo() {
                notImplemented('NetStream.multicastInfo');
                return this._multicastInfo;
              }
            },
            soundTransform: {
              get: function soundTransform() {
                return this._soundTransform;
              },
              set: function soundTransform(sndTransform) {
                somewhatImplemented('NetStream.soundTransform');
                this._soundTransform = sndTransform;
              }
            },
            checkPolicyFile: {
              get: function checkPolicyFile() {
                return this._checkPolicyFile;
              },
              set: function checkPolicyFile(state) {
                this._checkPolicyFile = state;
              }
            },
            client: {
              get: function client() {
                somewhatImplemented('NetStream.client');
                return this._client;
              },
              set: function client(object) {
                somewhatImplemented('NetStream.client');
                this._client = object;
              }
            },
            objectEncoding: {
              get: function objectEncoding() {
                notImplemented('NetStream.objectEncoding');
                return this._objectEncoding;
              }
            },
            multicastPushNeighborLimit: {
              get: function multicastPushNeighborLimit() {
                notImplemented('NetStream.multicastPushNeighborLimit');
                return this._multicastPushNeighborLimit;
              },
              set: function multicastPushNeighborLimit(neighbors) {
                notImplemented('NetStream.multicastPushNeighborLimit');
                this._multicastPushNeighborLimit = neighbors;
              }
            },
            multicastWindowDuration: {
              get: function multicastWindowDuration() {
                notImplemented('NetStream.multicastWindowDuration');
                return this._multicastWindowDuration;
              },
              set: function multicastWindowDuration(seconds) {
                notImplemented('NetStream.multicastWindowDuration');
                this._multicastWindowDuration = seconds;
              }
            },
            multicastRelayMarginDuration: {
              get: function multicastRelayMarginDuration() {
                notImplemented('NetStream.multicastRelayMarginDuration');
                return this._multicastRelayMarginDuration;
              },
              set: function multicastRelayMarginDuration(seconds) {
                notImplemented('NetStream.multicastRelayMarginDuration');
                this._multicastRelayMarginDuration = seconds;
              }
            },
            multicastAvailabilityUpdatePeriod: {
              get: function multicastAvailabilityUpdatePeriod() {
                notImplemented('NetStream.multicastAvailabilityUpdatePeriod');
                return this._multicastAvailabilityUpdatePeriod;
              },
              set: function multicastAvailabilityUpdatePeriod(seconds) {
                notImplemented('NetStream.multicastAvailabilityUpdatePeriod');
                this._multicastAvailabilityUpdatePeriod = seconds;
              }
            },
            multicastFetchPeriod: {
              get: function multicastFetchPeriod() {
                notImplemented('NetStream.multicastFetchPeriod');
                return this._multicastFetchPeriod;
              },
              set: function multicastFetchPeriod(seconds) {
                notImplemented('NetStream.multicastFetchPeriod');
                this._multicastFetchPeriod = seconds;
              }
            },
            multicastAvailabilitySendToAll: {
              get: function multicastAvailabilitySendToAll() {
                notImplemented('NetStream.multicastAvailabilitySendToAll');
                return this._multicastAvailabilitySendToAll;
              },
              set: function multicastAvailabilitySendToAll(value) {
                notImplemented('NetStream.multicastAvailabilitySendToAll');
                this._multicastAvailabilitySendToAll = value;
              }
            },
            farID: {
              get: function farID() {
                notImplemented('NetStream.farID');
                return this._farID;
              }
            },
            nearNonce: {
              get: function nearNonce() {
                notImplemented('NetStream.nearNonce');
                return this._nearNonce;
              }
            },
            farNonce: {
              get: function farNonce() {
                notImplemented('NetStream.farNonce');
                return this._farNonce;
              }
            },
            peerStreams: {
              get: function peerStreams() {
                notImplemented('NetStream.peerStreams');
                return this._peerStreams;
              }
            },
            audioReliable: {
              get: function audioReliable() {
                notImplemented('NetStream.audioReliable');
                return this._audioReliable;
              },
              set: function audioReliable(reliable) {
                notImplemented('NetStream.audioReliable');
                this._audioReliable = reliable;
              }
            },
            videoReliable: {
              get: function videoReliable() {
                notImplemented('NetStream.videoReliable');
                return this._videoReliable;
              },
              set: function videoReliable(reliable) {
                notImplemented('NetStream.videoReliable');
                this._videoReliable = reliable;
              }
            },
            dataReliable: {
              get: function dataReliable() {
                notImplemented('NetStream.dataReliable');
                return this._dataReliable;
              },
              set: function dataReliable(reliable) {
                notImplemented('NetStream.dataReliable');
                this._dataReliable = reliable;
              }
            },
            audioSampleAccess: {
              get: function audioSampleAccess() {
                notImplemented('NetStream.audioSampleAccess');
                return this._audioSampleAccess;
              },
              set: function audioSampleAccess(reliable) {
                notImplemented('NetStream.audioSampleAccess');
                this._audioSampleAccess = reliable;
              }
            },
            videoSampleAccess: {
              get: function videoSampleAccess() {
                notImplemented('NetStream.videoSampleAccess');
                return this._videoSampleAccess;
              },
              set: function videoSampleAccess(reliable) {
                notImplemented('NetStream.videoSampleAccess');
                this._videoSampleAccess = reliable;
              }
            },
            useHardwareDecoder: {
              get: function useHardwareDecoder() {
                notImplemented('NetStream.useHardwareDecoder');
                return this._useHardwareDecoder;
              },
              set: function useHardwareDecoder(v) {
                notImplemented('NetStream.useHardwareDecoder');
                this._useHardwareDecoder = v;
              }
            },
            useJitterBuffer: {
              get: function useJitterBuffer() {
                notImplemented('NetStream.useJitterBuffer');
                return this._useJitterBuffer;
              },
              set: function useJitterBuffer(value) {
                notImplemented('NetStream.useJitterBuffer');
                this._useJitterBuffer = value;
              }
            },
            videoStreamSettings: {
              get: function videoStreamSettings() {
                notImplemented('NetStream.videoStreamSettings');
                return this._videoStreamSettings;
              },
              set: function videoStreamSettings(settings) {
                notImplemented('NetStream.videoStreamSettings');
                this._videoStreamSettings = settings;
              }
            }
          }
        }
      }
    };
  }.call(this);
var ObjectEncodingDefinition = function () {
    return {
      __class__: 'flash.net.ObjectEncoding',
      initialize: function () {
      },
      __glue__: {
        native: {
          static: {
            dynamicPropertyWriter: {
              get: function dynamicPropertyWriter() {
                notImplemented('ObjectEncoding.dynamicPropertyWriter');
              },
              set: function dynamicPropertyWriter(object) {
                notImplemented('ObjectEncoding.dynamicPropertyWriter');
              }
            }
          },
          instance: {}
        }
      }
    };
  }.call(this);
var ResponderDefinition = function () {
    var def = {
        ctor: function (result, status) {
        }
      };
    def.__glue__ = {
      native: {
        instance: {
          ctor: def.ctor
        }
      }
    };
    return def;
  }.call(this);
var SharedObjectDefinition = function () {
    var _defaultObjectEncoding = 3;
    var sharedObjects = createEmptyObject();
    function invokeWithArgsArray(index, args) {
      var simulated = false, result;
      switch (index) {
      case 4:
        result = JSON.stringify(this._data).length - 2;
        simulated = true;
        break;
      case 6:
        this._data = {};
        sessionStorage.removeItem(this._path);
        simulated = true;
        break;
      case 2:
        sessionStorage.setItem(this._path, JSON.stringify(this._data));
        simulated = true;
        result = true;
        break;
      case 3:
        simulated = true;
        break;
      }
      (simulated ? somewhatImplemented : notImplemented)('SharedObject.invoke (' + index + ')');
      return result;
    }
    return {
      __class__: 'flash.net.SharedObject',
      initialize: function () {
        this._path = null;
        this._data = null;
        this._objectEncoding = _defaultObjectEncoding;
        TelemetryService.reportTelemetry({
          topic: 'feature',
          feature: SHAREDOBJECT_FEATURE
        });
      },
      __glue__: {
        native: {
          static: {
            deleteAll: function deleteAll(url) {
              notImplemented('SharedObject.deleteAll');
            },
            getDiskUsage: function getDiskUsage(url) {
              notImplemented('SharedObject.getDiskUsage');
            },
            getLocal: function getLocal(name, localPath, secure) {
              var path = (localPath || '') + '/' + name;
              if (sharedObjects[path]) {
                return sharedObjects[path];
              }
              var so = new flash.net.SharedObject();
              so._path = path;
              var data = sessionStorage.getItem(path);
              so._data = data ? JSON.parse(data) : {};
              return so;
            },
            getRemote: function getRemote(name, remotePath, persistence, secure) {
              notImplemented('SharedObject.getRemote');
            },
            defaultObjectEncoding: {
              get: function defaultObjectEncoding() {
                return _defaultObjectEncoding;
              },
              set: function defaultObjectEncoding(version) {
                _defaultObjectEncoding = version;
              }
            }
          },
          instance: {
            setDirty: function setDirty(propertyName) {
              somewhatImplemented('SharedObject.setDirty');
            },
            invoke: function invoke(index) {
              return invokeWithArgsArray.call(this, index, Array.prototype.slice.call(arguments, 1));
            },
            invokeWithArgsArray: function invokeWithArgsArray(index, args) {
              return invokeWithArgsArray.call(this, index, args);
            },
            data: {
              get: function data() {
                return this._data;
              }
            },
            objectEncoding: {
              get: function objectEncoding() {
                return this._objectEncoding;
              },
              set: function objectEncoding(version) {
                this._objectEncoding = version;
              }
            },
            client: {
              get: function client() {
                notImplemented('SharedObject.client');
                return this._client;
              },
              set: function client(object) {
                notImplemented('SharedObject.client');
                this._client = object;
              }
            }
          }
        }
      }
    };
  }.call(this);
var SocketDefinition = function () {
    return {
      __class__: 'flash.net.Socket',
      initialize: function () {
        this._connected = false;
      },
      __glue__: {
        native: {
          static: {},
          instance: {
            internalGetSecurityErrorMessage: function internalGetSecurityErrorMessage(host, port) {
              somewhatImplemented('Socket.internalGetSecurityErrorMessage');
              return 'SecurityErrorEvent';
            },
            internalConnect: function internalConnect(host, port) {
              somewhatImplemented('Socket.internalConnect');
              throwError('SecurityError', Errors.SocketConnectError, host, port);
            },
            didFailureOccur: function didFailureOccur() {
              somewhatImplemented('Socket.didFailureOccur');
              return true;
            },
            readBytes: function readBytes(bytes, offset, length) {
              notImplemented('Socket.readBytes');
            },
            writeBytes: function writeBytes(bytes, offset, length) {
              notImplemented('Socket.writeBytes');
            },
            writeBoolean: function writeBoolean(value) {
              notImplemented('Socket.writeBoolean');
            },
            writeByte: function writeByte(value) {
              notImplemented('Socket.writeByte');
            },
            writeShort: function writeShort(value) {
              notImplemented('Socket.writeShort');
            },
            writeInt: function writeInt(value) {
              notImplemented('Socket.writeInt');
            },
            writeUnsignedInt: function writeUnsignedInt(value) {
              notImplemented('Socket.writeUnsignedInt');
            },
            writeFloat: function writeFloat(value) {
              notImplemented('Socket.writeFloat');
            },
            writeDouble: function writeDouble(value) {
              notImplemented('Socket.writeDouble');
            },
            writeMultiByte: function writeMultiByte(value, charSet) {
              notImplemented('Socket.writeMultiByte');
            },
            writeUTF: function writeUTF(value) {
              notImplemented('Socket.writeUTF');
            },
            writeUTFBytes: function writeUTFBytes(value) {
              notImplemented('Socket.writeUTFBytes');
            },
            readBoolean: function readBoolean() {
              notImplemented('Socket.readBoolean');
            },
            readByte: function readByte() {
              notImplemented('Socket.readByte');
            },
            readUnsignedByte: function readUnsignedByte() {
              notImplemented('Socket.readUnsignedByte');
            },
            readShort: function readShort() {
              notImplemented('Socket.readShort');
            },
            readUnsignedShort: function readUnsignedShort() {
              notImplemented('Socket.readUnsignedShort');
            },
            readInt: function readInt() {
              notImplemented('Socket.readInt');
            },
            readUnsignedInt: function readUnsignedInt() {
              notImplemented('Socket.readUnsignedInt');
            },
            readFloat: function readFloat() {
              notImplemented('Socket.readFloat');
            },
            readDouble: function readDouble() {
              notImplemented('Socket.readDouble');
            },
            readMultiByte: function readMultiByte(length, charSet) {
              notImplemented('Socket.readMultiByte');
            },
            readUTF: function readUTF() {
              notImplemented('Socket.readUTF');
            },
            readUTFBytes: function readUTFBytes(length) {
              notImplemented('Socket.readUTFBytes');
            },
            internalClose: function internalClose() {
              notImplemented('Socket.internalClose');
            },
            flush: function flush() {
              notImplemented('Socket.flush');
            },
            writeObject: function writeObject(object) {
              notImplemented('Socket.writeObject');
            },
            readObject: function readObject() {
              notImplemented('Socket.readObject');
            },
            bytesAvailable: {
              get: function bytesAvailable() {
                notImplemented('Socket.bytesAvailable');
                return this._bytesAvailable;
              }
            },
            connected: {
              get: function connected() {
                somewhatImplemented('Socket.connected');
                return this._connected;
              }
            },
            objectEncoding: {
              get: function objectEncoding() {
                notImplemented('Socket.objectEncoding');
                return this._objectEncoding;
              },
              set: function objectEncoding(version) {
                notImplemented('Socket.objectEncoding');
                this._objectEncoding = version;
              }
            },
            endian: {
              get: function endian() {
                notImplemented('Socket.endian');
                return this._endian;
              },
              set: function endian(type) {
                notImplemented('Socket.endian');
                this._endian = type;
              }
            },
            bytesPending: {
              get: function bytesPending() {
                notImplemented('Socket.bytesPending');
                return this._bytesPending;
              }
            }
          }
        },
        script: {
          instance: Glue.ALL
        }
      }
    };
  }.call(this);
var URLLoaderDefinition = function () {
    return {
      initialize: function () {
      },
      __glue__: {
        native: {
          static: {},
          instance: {}
        },
        script: {
          static: {},
          instance: {
            data: 'public data',
            dataFormat: 'public dataFormat',
            bytesTotal: 'public bytesTotal',
            bytesLoaded: 'public bytesLoaded',
            load: 'public load'
          }
        }
      }
    };
  }.call(this);
var URLRequestDefinition = function () {
    function toFileLoadingServiceRequest() {
      var obj = {};
      obj.url = this._url;
      obj.method = this._method;
      obj.checkPolicyFile = this._checkPolicyFile;
      if (this._data) {
        obj.mimeType = this._contentType;
        var ByteArrayClass = avm2.systemDomain.getClass('flash.utils.ByteArray');
        if (ByteArrayClass.isInstanceOf(this._data)) {
          obj.data = new Uint8Array(this._data.a, 0, this._data.length);
        } else {
          var data = this._data.asGetPublicProperty('toString').call(this._data);
          if (this._method === 'GET') {
            var i = obj.url.lastIndexOf('?');
            obj.url = (i < 0 ? obj.url : obj.url.substring(0, i)) + '?' + data;
          } else {
            obj.data = data;
          }
        }
      }
      return obj;
    }
    var def = {
        initialize: function () {
          this._url = null;
          this._method = 'GET';
          this._data = null;
          this._digest = null;
          this._contentType = 'application/x-www-form-urlencoded';
          this._requestHeaders = null;
          this._checkPolicyFile = true;
          this._toFileRequest = toFileLoadingServiceRequest;
        },
        setMethod: function (val) {
          this._method = val;
        },
        setRequestHeaders: function (val) {
          this._requestHeaders = val;
        },
        get contentType() {
          return this._contentType;
        },
        set contentType(val) {
          this._contentType = val;
        },
        get data() {
          return this._data;
        },
        set data(val) {
          this._data = val;
        },
        get digest() {
          return this._digest;
        },
        set digest(val) {
          this._digest = val;
        },
        get method() {
          return this._method;
        },
        set method(method) {
          this._method = method;
        },
        get requestHeaders() {
          return this._requestHeaders;
        },
        set requestHeaders(requestHeaders) {
          this._requestHeaders = requestHeaders;
        },
        get url() {
          return this._url;
        },
        set url(val) {
          this._url = val;
        }
      };
    var desc = Object.getOwnPropertyDescriptor;
    def.__glue__ = {
      native: {
        instance: {
          setMethod: def.setMethod,
          setRequestHeaders: def.setRequestHeaders,
          contentType: desc(def, 'contentType'),
          data: desc(def, 'data'),
          digest: desc(def, 'digest'),
          method: desc(def, 'method'),
          requestHeaders: desc(def, 'requestHeaders'),
          url: desc(def, 'url')
        }
      }
    };
    return def;
  }.call(this);
var URLStreamDefinition = function () {
    var def = {
        initialize: function () {
          this._stream = null;
          this._connected = false;
          this._littleEndian = false;
        },
        close: function close() {
          this._session.close();
        },
        load: function load(request) {
          var session = FileLoadingService.createSession();
          var self = this;
          var initStream = true;
          session.onprogress = function (data, progressState) {
            if (initStream) {
              initStream = false;
              var length = Math.max(progressState.bytesTotal, data.length);
              var buffer = new ArrayBuffer(length);
              self._stream = new Stream(buffer, 0, 0, length);
            } else if (self._stream.end + data.length > self._stream.bytes.length) {
              var length = self._stream.end + data.length;
              var buffer = new ArrayBuffer(length);
              var newStream = new Stream(buffer, 0, 0, length);
              newStream.push(self._stream.bytes.subarray(0, self._stream.end));
              self._stream = newStream;
            }
            self._stream.push(data);
            var ProgressEventClass = avm2.systemDomain.getClass('flash.events.ProgressEvent');
            self._dispatchEvent(ProgressEventClass.createInstance([
              'progress',
              false,
              false,
              progressState.bytesLoaded,
              progressState.bytesTotal
            ]));
          };
          session.onerror = function (error) {
            self._connected = false;
            if (!self._stream) {
              self._stream = new Stream(new ArrayBuffer(0), 0, 0, 0);
            }
            self._dispatchEvent(new flash.events.IOErrorEvent(flash.events.IOErrorEvent.class.IO_ERROR, false, false, error));
          };
          session.onopen = function () {
            self._connected = true;
            self._dispatchEvent(new flash.events.Event('open', false, false));
          };
          session.onhttpstatus = function (location, httpStatus, httpHeaders) {
            var HTTPStatusEventClass = avm2.systemDomain.getClass('flash.events.HTTPStatusEvent');
            var URLRequestHeaderClass = avm2.systemDomain.getClass('flash.net.URLRequestHeader');
            var httpStatusEvent = HTTPStatusEventClass.createInstance([
                'httpStatus',
                false,
                false,
                httpStatus
              ]);
            var headers = [];
            httpHeaders.split(/(?:\n|\r?\n)/g).forEach(function (h) {
              var m = /^([^:]+): (.*)$/.exec(h);
              if (m) {
                headers.push(URLRequestHeaderClass.createInstance([
                  m[1],
                  m[2]
                ]));
                if (m[1] === 'Location') {
                  location = m[2];
                }
              }
            });
            httpStatusEvent.asSetPublicProperty('responseHeaders', headers);
            httpStatusEvent.asSetPublicProperty('responseURL', location);
            self._dispatchEvent(httpStatusEvent);
          };
          session.onclose = function () {
            self._connected = false;
            if (!self._stream) {
              self._stream = new Stream(new ArrayBuffer(0), 0, 0, 0);
            }
            self._dispatchEvent(new flash.events.Event('complete', false, false));
          };
          session.open(request._toFileRequest());
          this._session = session;
        },
        readBoolean: function readBoolean() {
          notImplemented('URLStream.readBoolean');
        },
        readByte: function readByte() {
          var stream = this._stream;
          stream.ensure(1);
          return stream.bytes[stream.pos++];
        },
        readBytes: function readBytes(bytes, offset, length) {
          if (length < 0)
            throw 'Invalid length argument';
          var stream = this._stream;
          if (!length)
            length = stream.remaining();
          else
            stream.ensure(length);
          bytes.writeRawBytes(stream.bytes.subarray(stream.pos, stream.pos + length), offset, length);
          stream.pos += length;
        },
        readDouble: function readDouble() {
          notImplemented('URLStream.readDouble');
        },
        readFloat: function readFloat() {
          notImplemented('URLStream.readFloat');
        },
        readInt: function readInt() {
          notImplemented('URLStream.readInt');
        },
        readMultiByte: function readMultiByte(length, charSet) {
          notImplemented('URLStream.readMultiByte');
        },
        readObject: function readObject() {
          notImplemented('URLStream.readObject');
        },
        readShort: function readShort() {
          notImplemented('URLStream.readShort');
        },
        readUTF: function readUTF() {
          return this.readUTFBytes(this.readUnsignedShort());
        },
        readUTFBytes: function readUTFBytes(length) {
          if (length < 0)
            throw 'Invalid length argument';
          var stream = this._stream;
          stream.ensure(length);
          var str = utf8encode(stream.bytes.subarray(stream.pos, stream.pos + length));
          stream.pos += length;
          return str;
        },
        readUnsignedByte: function readUnsignedByte() {
          notImplemented('URLStream.readUnsignedByte');
        },
        readUnsignedInt: function readUnsignedInt() {
          notImplemented('URLStream.readUnsignedInt');
        },
        readUnsignedShort: function readUnsignedShort() {
          var stream = this._stream;
          stream.ensure(2);
          var result = stream.getUint16(stream.pos, this._littleEndian);
          stream.pos += 2;
          return result;
        },
        get bytesAvailable() {
          return this._stream.remaining();
        },
        get connected() {
          return this._connected;
        },
        get endian() {
          return this._littleEndian ? 'littleEndian' : 'bigEndian';
        },
        set endian(val) {
          this._littleEndian = val == 'littleEndian';
        },
        get objectEncoding() {
          notImplemented('URLStream.objectEncoding');
        },
        set objectEncoding(val) {
          notImplemented('URLStream.objectEncoding');
        }
      };
    var desc = Object.getOwnPropertyDescriptor;
    def.__glue__ = {
      native: {
        instance: {
          close: def.close,
          load: def.load,
          readBoolean: def.readBoolean,
          readByte: def.readByte,
          readBytes: def.readBytes,
          readDouble: def.readDouble,
          readFloat: def.readFloat,
          readInt: def.readInt,
          readMultiByte: def.readMultiByte,
          readObject: def.readObject,
          readShort: def.readShort,
          readUTF: def.readUTF,
          readUTFBytes: def.readUTFBytes,
          readUnsignedByte: def.readUnsignedByte,
          readUnsignedInt: def.readUnsignedInt,
          readUnsignedShort: def.readUnsignedShort,
          bytesAvailable: desc(def, 'bytesAvailable'),
          connected: desc(def, 'connected'),
          endian: desc(def, 'endian'),
          objectEncoding: desc(def, 'objectEncoding')
        }
      }
    };
    return def;
  }.call(this);
{
  var ApplicationDomainDefinition = function () {
      return {
        __class__: 'flash.system.ApplicationDomain',
        initialize: function () {
        },
        __glue__: {
          native: {
            static: {
              currentDomain: {
                get: function currentDomain() {
                  return new flash.system.ApplicationDomain(AVM2.currentDomain());
                }
              },
              MIN_DOMAIN_MEMORY_LENGTH: {
                get: function MIN_DOMAIN_MEMORY_LENGTH() {
                  notImplemented('ApplicationDomain.MIN_DOMAIN_MEMORY_LENGTH');
                }
              }
            },
            instance: {
              ctor: function ctor(parentDomainOrNativeObject) {
                if (parentDomainOrNativeObject instanceof ApplicationDomain) {
                  this.nativeObject = parentDomainOrNativeObject;
                  return;
                }
                var parentNativeObject = parentDomainOrNativeObject ? parentDomainOrNativeObject.nativeObject : AVM2.currentDomain().system;
                this.nativeObject = new ApplicationDomain(parentNativeObject.vm, parentNativeObject);
              },
              getDefinition: function getDefinition(name) {
                var simpleName = name.replace('::', '.');
                return this.nativeObject.getProperty(Multiname.fromSimpleName(simpleName), true, true);
              },
              hasDefinition: function hasDefinition(name) {
                if (name === undefined) {
                  return false;
                }
                var simpleName = name.replace('::', '.');
                return !(!this.nativeObject.findDomainProperty(Multiname.fromSimpleName(simpleName), false, false));
              },
              getQualifiedDefinitionNames: function getQualifiedDefinitionNames() {
                notImplemented('ApplicationDomain.getQualifiedDefinitionNames');
              },
              parentDomain: {
                get: function parentDomain() {
                  var base = this.nativeObject.base;
                  if (!base) {
                    return undefined;
                  }
                  return new flash.system.ApplicationDomain(base);
                }
              },
              domainMemory: {
                get: function domainMemory() {
                  notImplemented('ApplicationDomain.domainMemory');
                  return this._domainMemory;
                },
                set: function domainMemory(mem) {
                  notImplemented('ApplicationDomain.domainMemory');
                  this._domainMemory = mem;
                }
              }
            }
          },
          script: {
            static: Glue.ALL,
            instance: Glue.ALL
          }
        }
      };
    }.call(this);
}
var CapabilitiesDefinition = function () {
    var def = {};
    var os;
    var userAgent = window.navigator.userAgent;
    if (userAgent.indexOf('Macintosh') > 0) {
      os = 'Mac OS 10.5.2';
    } else if (userAgent.indexOf('Windows') > 0) {
      os = 'Windows XP';
    } else if (userAgent.indexOf('Linux') > 0) {
      os = 'Linux';
    } else if (/(iPad|iPhone|iPod|Android)/.test(userAgent)) {
      os = 'iPhone3,1';
    } else {
      notImplemented();
    }
    def.__glue__ = {
      native: {
        static: {
          version: {
            get: function version() {
              return 'SHUMWAY 10,0,0,0';
            },
            enumerable: true
          },
          os: {
            get: function () {
              return os;
            },
            enumerable: true
          },
          serverString: {
            get: function () {
              var str = toKeyValueArray({
                  OS: os
                }).map(function (pair) {
                  return pair[0] + '=' + encodeURIComponent(pair[1]);
                }).join('&');
              somewhatImplemented('Capabilities.serverString: ' + str);
              return str;
            }
          },
          hasAccessibility: {
            get: function hasAccessibility() {
              somewhatImplemented('Capabilities.hasAccessibility');
              return false;
            }
          },
          isDebugger: {
            get: function isDebugger() {
              return false;
            }
          },
          screenResolutionX: {
            get: function screenResolutionX() {
              return window.screen.width;
            }
          },
          screenResolutionY: {
            get: function screenResolutionY() {
              return window.screen.height;
            }
          },
          manufacturer: {
            get: function manufacturer() {
              somewhatImplemented('Capabilities.manufacturer');
              return 'Mozilla Research';
            }
          },
          language: {
            get: function language() {
              somewhatImplemented('Capabilities.language');
              return 'en';
            }
          },
          playerType: {
            get: function playerType() {
              somewhatImplemented('Capabilities.playerType');
              return 'PlugIn';
            }
          }
        }
      },
      script: {
        static: scriptProperties('public', [
          'version',
          'os'
        ])
      }
    };
    return def;
  }.call(this);
var FSCommandDefinition = function () {
    var def = {};
    function fscommand(command, parameters) {
      console.log('FSCommand: ' + command + '; ' + parameters);
      switch (command.toLowerCase()) {
      case 'quit':
        renderingTerminated = true;
        return;
      case 'debugger':
        debugger;
        return;
      default:
        break;
      }
    }
    def.__glue__ = {
      native: {
        static: {
          _fscommand: fscommand
        }
      }
    };
    return def;
  }.call(this);
var SecurityDefinition = function () {
    var _exactSettings;
    return {
      __class__: 'flash.system.Security',
      initialize: function () {
      },
      __glue__: {
        native: {
          static: {
            allowDomain: function allowDomain() {
              somewhatImplemented('Security.allowDomain ["' + Array.prototype.join.call(arguments, '", "') + '"]');
            },
            allowInsecureDomain: function allowInsecureDomain() {
              somewhatImplemented('Security.allowInsecureDomain');
            },
            loadPolicyFile: function loadPolicyFile(url) {
              somewhatImplemented('Security.loadPolicyFile');
            },
            duplicateSandboxBridgeInputArguments: function duplicateSandboxBridgeInputArguments(toplevel, args) {
              notImplemented('Security.duplicateSandboxBridgeInputArguments');
            },
            duplicateSandboxBridgeOutputArgument: function duplicateSandboxBridgeOutputArgument(toplevel, arg) {
              notImplemented('Security.duplicateSandboxBridgeOutputArgument');
            },
            showSettings: function showSettings(panel) {
              notImplemented('Security.showSettings');
            },
            exactSettings: {
              get: function () {
                return _exactSettings;
              },
              set: function (value) {
                _exactSettings = value;
              }
            },
            disableAVM1Loading: {
              get: function disableAVM1Loading() {
                notImplemented('Security.disableAVM1Loading');
              },
              set: function disableAVM1Loading(value) {
                notImplemented('Security.disableAVM1Loading');
              }
            },
            sandboxType: {
              get: function () {
                somewhatImplemented('Security.sandboxType');
                return 'remote';
              }
            },
            pageDomain: {
              get: function pageDomain() {
                somewhatImplemented('Security.pageDomain');
                var pageHost = FileLoadingService.resolveUrl('/');
                var parts = pageHost.split('/');
                parts.pop();
                return parts.pop();
              }
            }
          }
        }
      }
    };
  }.call(this);
var SecurityDomainDefinition = function () {
    return {
      __class__: 'flash.system.SecurityDomain',
      initialize: function () {
      },
      _currentDomain: null,
      __glue__: {
        native: {
          static: {
            currentDomain: {
              get: function () {
                return this._currentDomain;
              }
            }
          },
          instance: {
            ctor_impl: function ctor_impl() {
              notImplemented('SecurityDomain.ctor_impl');
            },
            domainID: {
              get: function domainID() {
                notImplemented('SecurityDomain.domainID');
                return this._domainID;
              }
            }
          }
        }
      }
    };
  }.call(this);
var SystemDefinition = function () {
    return {
      __class__: 'flash.system.System',
      initialize: function () {
      },
      __glue__: {
        native: {
          static: {
            setClipboard: function setClipboard(string) {
              FirefoxCom.request('setClipboard', string);
              TelemetryService.reportTelemetry({
                topic: 'feature',
                feature: CLIPBOARD_FEATURE
              });
            },
            pause: function pause() {
              somewhatImplemented('System.pause');
            },
            resume: function resume() {
              somewhatImplemented('System.resume');
            },
            exit: function exit(code) {
              somewhatImplemented('System.exit');
              renderingTerminated = true;
            },
            gc: function gc() {
              somewhatImplemented('System.gc');
            },
            pauseForGCIfCollectionImminent: function pauseForGCIfCollectionImminent(imminence) {
              notImplemented('System.pauseForGCIfCollectionImminent');
            },
            disposeXML: function disposeXML(node) {
              notImplemented('System.disposeXML');
            },
            ime: {
              get: function ime() {
                notImplemented('System.ime');
              }
            },
            totalMemoryNumber: {
              get: function totalMemoryNumber() {
                if (performance.memory) {
                  return performance.memory.usedJSHeapSize;
                }
                return 0;
              }
            },
            freeMemory: {
              get: function freeMemory() {
                notImplemented('System.freeMemory');
              }
            },
            privateMemory: {
              get: function privateMemory() {
                return 0;
              }
            },
            processCPUUsage: {
              get: function processCPUUsage() {
                notImplemented('System.processCPUUsage');
              }
            },
            useCodePage: {
              get: function useCodePage() {
                somewhatImplemented('System.useCodePage');
                return false;
              },
              set: function useCodePage(value) {
                notImplemented('System.useCodePage');
              }
            },
            vmVersion: {
              get: function vmVersion() {
                somewhatImplemented('System.vmVersion');
                return '1.0 shumway';
              }
            },
            swfVersion: {
              get: function () {
                return 19;
              }
            },
            apiVersion: {
              get: function () {
                return 26;
              }
            },
            getArgv: function () {
              return [];
            },
            getRunmode: function () {
              return 'mixed';
            }
          },
          instance: {}
        }
      }
    };
  }.call(this);
{
  var FontDefinition = function () {
      var fonts = [];
      var fontsByUniqueName = Object.create(null);
      var fontsByNameStyleType = Object.create(null);
      var _deviceFontMetrics;
      var def = {
          __class__: 'flash.text.Font',
          initialize: function () {
            var s = this.symbol;
            if (s) {
              this._fontName = s.name || null;
              this._uniqueName = s.uniqueName;
              if (s.bold) {
                if (s.italic) {
                  this._fontStyle = 'boldItalic';
                } else {
                  this._fontStyle = 'bold';
                }
              } else if (s.italic) {
                this._fontStyle = 'italic';
              } else {
                this._fontStyle = 'regular';
              }
              var metrics = s.metrics;
              metrics.height = metrics.ascent + metrics.descent + metrics.leading;
              this._metrics = metrics;
              this._fontType = 'embedded';
              fonts.push(this);
              fontsByUniqueName[this._uniqueName] = this;
              var ident = this._fontName.toLowerCase() + '_' + this._fontStyle + '_embedded';
              fontsByNameStyleType[ident] = this;
            }
          },
          get fontName() {
            return this._fontName;
          },
          get fontStyle() {
            return this._fontStyle;
          },
          get fontType() {
            return this._fontType;
          },
          hasGlyphs: function hasGlyphs(str) {
            return true;
          },
          getFont: function (name, style, embedded) {
            var ident = name.toLowerCase() + '_' + style + (embedded ? '_embedded' : '_device');
            var font = fontsByNameStyleType[ident];
            if (font) {
              return font;
            }
            font = new flash.text.Font();
            font._fontName = font._uniqueName = name;
            font._fontStyle = style;
            font._fontType = 'device';
            var metrics = deviceFontMetrics()[name];
            if (!metrics) {
              metrics = deviceFontMetrics().serif;
              font._fontName = font._uniqueName = 'serif';
            }
            font._metrics = {
              ascent: metrics[0],
              descent: metrics[1],
              leading: metrics[2]
            };
            font._metrics.height = metrics[0] + metrics[1] + metrics[2];
            fontsByNameStyleType[ident] = font;
            return font;
          },
          getFontByUniqueName: function (name) {
            return fontsByUniqueName[name];
          }
        };
      function enumerateFonts(device) {
        return fonts.slice();
      }
      function registerFont(font) {
        somewhatImplemented('Font.registerFont');
      }
      function deviceFontMetrics() {
        if (_deviceFontMetrics) {
          return _deviceFontMetrics;
        }
        var userAgent = window.navigator.userAgent;
        if (userAgent.indexOf('Windows') > -1) {
          _deviceFontMetrics = DEVICE_FONT_METRICS_WIN;
        } else if (/(Macintosh|iPad|iPhone|iPod|Android)/.test(userAgent)) {
          _deviceFontMetrics = DEVICE_FONT_METRICS_MAC;
        } else {
          _deviceFontMetrics = DEVICE_FONT_METRICS_LINUX;
        }
        return _deviceFontMetrics;
      }
      var desc = Object.getOwnPropertyDescriptor;
      def.__glue__ = {
        native: {
          instance: {
            fontName: desc(def, 'fontName'),
            fontStyle: desc(def, 'fontStyle'),
            fontType: desc(def, 'fontType'),
            hasGlyphs: def.hasGlyphs
          },
          static: {
            enumerateFonts: enumerateFonts,
            registerFont: registerFont
          }
        }
      };
      return def;
    }.call(this);
  var DEVICE_FONT_METRICS_WIN = {
      'serif': [
        1,
        0.25,
        0
      ],
      'sans-serif': [
        1,
        0.25,
        0
      ],
      'monospace': [
        1,
        0.25,
        0
      ],
      'birch std': [
        0.9167,
        0.25,
        0
      ],
      'blackoak std': [
        1,
        0.3333,
        0
      ],
      'chaparral pro': [
        0.8333,
        0.3333,
        0
      ],
      'chaparral pro light': [
        0.8333,
        0.3333,
        0
      ],
      'charlemagne std': [
        0.9167,
        0.25,
        0
      ],
      'cooper std black': [
        0.9167,
        0.25,
        0
      ],
      'giddyup std': [
        0.8333,
        0.3333,
        0
      ],
      'hobo std': [
        1.0833,
        0.3333,
        0
      ],
      'kozuka gothic pro b': [
        1,
        0.4167,
        0
      ],
      'kozuka gothic pro el': [
        1.0833,
        0.25,
        0
      ],
      'kozuka gothic pro h': [
        1,
        0.4167,
        0
      ],
      'kozuka gothic pro l': [
        1,
        0.3333,
        0
      ],
      'kozuka gothic pro m': [
        1.0833,
        0.3333,
        0
      ],
      'kozuka gothic pro r': [
        1,
        0.3333,
        0
      ],
      'kozuka mincho pro b': [
        1.0833,
        0.25,
        0
      ],
      'kozuka mincho pro el': [
        1.0833,
        0.25,
        0
      ],
      'kozuka mincho pro h': [
        1.1667,
        0.25,
        0
      ],
      'kozuka mincho pro l': [
        1.0833,
        0.25,
        0
      ],
      'kozuka mincho pro m': [
        1.0833,
        0.25,
        0
      ],
      'kozuka mincho pro r': [
        1.0833,
        0.25,
        0
      ],
      'mesquite std': [
        0.9167,
        0.25,
        0
      ],
      'minion pro cond': [
        1,
        0.3333,
        0
      ],
      'minion pro med': [
        1,
        0.3333,
        0
      ],
      'minion pro smbd': [
        1,
        0.3333,
        0
      ],
      'myriad arabic': [
        1,
        0.4167,
        0
      ],
      'nueva std': [
        0.75,
        0.25,
        0
      ],
      'nueva std cond': [
        0.75,
        0.25,
        0
      ],
      'ocr a std': [
        0.8333,
        0.25,
        0
      ],
      'orator std': [
        1.0833,
        0.25,
        0
      ],
      'poplar std': [
        0.9167,
        0.25,
        0
      ],
      'prestige elite std': [
        0.9167,
        0.25,
        0
      ],
      'rosewood std regular': [
        0.8333,
        0.3333,
        0
      ],
      'stencil std': [
        1,
        0.3333,
        0
      ],
      'trajan pro': [
        1,
        0.25,
        0
      ],
      'kozuka gothic pr6n b': [
        1.4167,
        0.4167,
        0
      ],
      'kozuka gothic pr6n el': [
        1.4167,
        0.3333,
        0
      ],
      'kozuka gothic pr6n h': [
        1.4167,
        0.4167,
        0
      ],
      'kozuka gothic pr6n l': [
        1.4167,
        0.3333,
        0
      ],
      'kozuka gothic pr6n m': [
        1.5,
        0.3333,
        0
      ],
      'kozuka gothic pr6n r': [
        1.4167,
        0.3333,
        0
      ],
      'kozuka mincho pr6n b': [
        1.3333,
        0.3333,
        0
      ],
      'kozuka mincho pr6n el': [
        1.3333,
        0.3333,
        0
      ],
      'kozuka mincho pr6n h': [
        1.4167,
        0.3333,
        0
      ],
      'kozuka mincho pr6n l': [
        1.3333,
        0.3333,
        0
      ],
      'kozuka mincho pr6n m': [
        1.3333,
        0.3333,
        0
      ],
      'kozuka mincho pr6n r': [
        1.3333,
        0.3333,
        0
      ],
      'letter gothic std': [
        1,
        0.25,
        0
      ],
      'minion pro': [
        1,
        0.3333,
        0
      ],
      'myriad hebrew': [
        0.8333,
        0.3333,
        0
      ],
      'myriad pro': [
        0.9167,
        0.25,
        0
      ],
      'myriad pro cond': [
        0.9167,
        0.25,
        0
      ],
      'myriad pro light': [
        1,
        0.25,
        0
      ],
      'marlett': [
        1,
        0,
        0
      ],
      'arial': [
        1,
        0.25,
        0
      ],
      'arabic transparent': [
        1,
        0.25,
        0
      ],
      'arial baltic': [
        1,
        0.25,
        0
      ],
      'arial ce': [
        1,
        0.25,
        0
      ],
      'arial cyr': [
        1,
        0.25,
        0
      ],
      'arial greek': [
        1,
        0.25,
        0
      ],
      'arial tur': [
        1,
        0.25,
        0
      ],
      'batang': [
        0.8333,
        0.1667,
        0
      ],
      'batangche': [
        0.8333,
        0.1667,
        0
      ],
      'gungsuh': [
        0.8333,
        0.1667,
        0
      ],
      'gungsuhche': [
        0.8333,
        0.1667,
        0
      ],
      'courier new': [
        1,
        0.25,
        0
      ],
      'courier new baltic': [
        1,
        0.25,
        0
      ],
      'courier new ce': [
        1,
        0.25,
        0
      ],
      'courier new cyr': [
        1,
        0.25,
        0
      ],
      'courier new greek': [
        1,
        0.25,
        0
      ],
      'courier new tur': [
        1,
        0.25,
        0
      ],
      'daunpenh': [
        0.6667,
        0.6667,
        0
      ],
      'dokchampa': [
        1.4167,
        0.5833,
        0
      ],
      'estrangelo edessa': [
        0.75,
        0.3333,
        0
      ],
      'euphemia': [
        1.0833,
        0.3333,
        0
      ],
      'gautami': [
        1.1667,
        0.8333,
        0
      ],
      'vani': [
        1.0833,
        0.75,
        0
      ],
      'gulim': [
        0.8333,
        0.1667,
        0
      ],
      'gulimche': [
        0.8333,
        0.1667,
        0
      ],
      'dotum': [
        0.8333,
        0.1667,
        0
      ],
      'dotumche': [
        0.8333,
        0.1667,
        0
      ],
      'impact': [
        1.0833,
        0.25,
        0
      ],
      'iskoola pota': [
        1,
        0.3333,
        0
      ],
      'kalinga': [
        1.0833,
        0.5,
        0
      ],
      'kartika': [
        1,
        0.4167,
        0
      ],
      'khmer ui': [
        1.0833,
        0.3333,
        0
      ],
      'lao ui': [
        1,
        0.25,
        0
      ],
      'latha': [
        1.0833,
        0.4167,
        0
      ],
      'lucida console': [
        0.75,
        0.25,
        0
      ],
      'malgun gothic': [
        1,
        0.25,
        0
      ],
      'mangal': [
        1.0833,
        0.3333,
        0
      ],
      'meiryo': [
        1.0833,
        0.4167,
        0
      ],
      'meiryo ui': [
        1,
        0.25,
        0
      ],
      'microsoft himalaya': [
        0.5833,
        0.4167,
        0
      ],
      'microsoft jhenghei': [
        1,
        0.3333,
        0
      ],
      'microsoft yahei': [
        1.0833,
        0.3333,
        0
      ],
      'mingliu': [
        0.8333,
        0.1667,
        0
      ],
      'pmingliu': [
        0.8333,
        0.1667,
        0
      ],
      'mingliu_hkscs': [
        0.8333,
        0.1667,
        0
      ],
      'mingliu-extb': [
        0.8333,
        0.1667,
        0
      ],
      'pmingliu-extb': [
        0.8333,
        0.1667,
        0
      ],
      'mingliu_hkscs-extb': [
        0.8333,
        0.1667,
        0
      ],
      'mongolian baiti': [
        0.8333,
        0.25,
        0
      ],
      'ms gothic': [
        0.8333,
        0.1667,
        0
      ],
      'ms pgothic': [
        0.8333,
        0.1667,
        0
      ],
      'ms ui gothic': [
        0.8333,
        0.1667,
        0
      ],
      'ms mincho': [
        0.8333,
        0.1667,
        0
      ],
      'ms pmincho': [
        0.8333,
        0.1667,
        0
      ],
      'mv boli': [
        1.1667,
        0.25,
        0
      ],
      'microsoft new tai lue': [
        1,
        0.4167,
        0
      ],
      'nyala': [
        0.9167,
        0.3333,
        0
      ],
      'microsoft phagspa': [
        1.0833,
        0.25,
        0
      ],
      'plantagenet cherokee': [
        1,
        0.4167,
        0
      ],
      'raavi': [
        1.0833,
        0.6667,
        0
      ],
      'segoe script': [
        1.0833,
        0.5,
        0
      ],
      'segoe ui': [
        1,
        0.25,
        0
      ],
      'segoe ui semibold': [
        1,
        0.25,
        0
      ],
      'segoe ui light': [
        1,
        0.25,
        0
      ],
      'segoe ui symbol': [
        1,
        0.25,
        0
      ],
      'shruti': [
        1.0833,
        0.5,
        0
      ],
      'simsun': [
        0.8333,
        0.1667,
        0
      ],
      'nsimsun': [
        0.8333,
        0.1667,
        0
      ],
      'simsun-extb': [
        0.8333,
        0.1667,
        0
      ],
      'sylfaen': [
        1,
        0.3333,
        0
      ],
      'microsoft tai le': [
        1,
        0.3333,
        0
      ],
      'times new roman': [
        1,
        0.25,
        0
      ],
      'times new roman baltic': [
        1,
        0.25,
        0
      ],
      'times new roman ce': [
        1,
        0.25,
        0
      ],
      'times new roman cyr': [
        1,
        0.25,
        0
      ],
      'times new roman greek': [
        1,
        0.25,
        0
      ],
      'times new roman tur': [
        1,
        0.25,
        0
      ],
      'tunga': [
        1.0833,
        0.75,
        0
      ],
      'vrinda': [
        1,
        0.4167,
        0
      ],
      'shonar bangla': [
        0.8333,
        0.5,
        0
      ],
      'microsoft yi baiti': [
        0.8333,
        0.1667,
        0
      ],
      'tahoma': [
        1,
        0.1667,
        0
      ],
      'microsoft sans serif': [
        1.0833,
        0.1667,
        0
      ],
      'angsana new': [
        0.9167,
        0.4167,
        0
      ],
      'aparajita': [
        0.75,
        0.4167,
        0
      ],
      'cordia new': [
        0.9167,
        0.5,
        0
      ],
      'ebrima': [
        1.0833,
        0.5,
        0
      ],
      'gisha': [
        0.9167,
        0.25,
        0
      ],
      'kokila': [
        0.8333,
        0.3333,
        0
      ],
      'leelawadee': [
        0.9167,
        0.25,
        0
      ],
      'microsoft uighur': [
        1.0833,
        0.5,
        0
      ],
      'moolboran': [
        0.6667,
        0.6667,
        0
      ],
      'symbol': [
        1,
        0.25,
        0
      ],
      'utsaah': [
        0.8333,
        0.4167,
        0
      ],
      'vijaya': [
        1.0833,
        0.25,
        0
      ],
      'wingdings': [
        0.9167,
        0.25,
        0
      ],
      'andalus': [
        1.3333,
        0.4167,
        0
      ],
      'arabic typesetting': [
        0.8333,
        0.5,
        0
      ],
      'simplified arabic': [
        1.3333,
        0.5,
        0
      ],
      'simplified arabic fixed': [
        1,
        0.4167,
        0
      ],
      'sakkal majalla': [
        0.9167,
        0.5,
        0
      ],
      'traditional arabic': [
        1.3333,
        0.5,
        0
      ],
      'aharoni': [
        0.75,
        0.25,
        0
      ],
      'david': [
        0.75,
        0.25,
        0
      ],
      'frankruehl': [
        0.75,
        0.25,
        0
      ],
      'fangsong': [
        0.8333,
        0.1667,
        0
      ],
      'simhei': [
        0.8333,
        0.1667,
        0
      ],
      'kaiti': [
        0.8333,
        0.1667,
        0
      ],
      'browallia new': [
        0.8333,
        0.4167,
        0
      ],
      'lucida sans unicode': [
        1.0833,
        0.25,
        0
      ],
      'arial black': [
        1.0833,
        0.3333,
        0
      ],
      'calibri': [
        0.9167,
        0.25,
        0
      ],
      'cambria': [
        0.9167,
        0.25,
        0
      ],
      'cambria math': [
        3.0833,
        2.5,
        0
      ],
      'candara': [
        0.9167,
        0.25,
        0
      ],
      'comic sans ms': [
        1.0833,
        0.3333,
        0
      ],
      'consolas': [
        0.9167,
        0.25,
        0
      ],
      'constantia': [
        0.9167,
        0.25,
        0
      ],
      'corbel': [
        0.9167,
        0.25,
        0
      ],
      'franklin gothic medium': [
        1,
        0.3333,
        0
      ],
      'gabriola': [
        1.1667,
        0.6667,
        0
      ],
      'georgia': [
        1,
        0.25,
        0
      ],
      'palatino linotype': [
        1.0833,
        0.3333,
        0
      ],
      'segoe print': [
        1.25,
        0.5,
        0
      ],
      'trebuchet ms': [
        1.0833,
        0.4167,
        0
      ],
      'verdana': [
        1,
        0.1667,
        0
      ],
      'webdings': [
        1.0833,
        0.5,
        0
      ],
      'lucida bright': [
        0.9167,
        0.25,
        0
      ],
      'lucida sans': [
        0.9167,
        0.25,
        0
      ],
      'lucida sans typewriter': [
        0.9167,
        0.25,
        0
      ],
      'gentium basic': [
        0.8333,
        0.25,
        0
      ],
      'dejavu serif condensed': [
        0.9167,
        0.25,
        0
      ],
      'arimo': [
        1,
        0.25,
        0
      ],
      'dejavu sans condensed': [
        0.9167,
        0.25,
        0
      ],
      'dejavu sans': [
        0.9167,
        0.25,
        0
      ],
      'dejavu sans light': [
        0.9167,
        0.25,
        0
      ],
      'opensymbol': [
        0.8333,
        0.1667,
        0
      ],
      'gentium book basic': [
        0.8333,
        0.25,
        0
      ],
      'dejavu sans mono': [
        0.9167,
        0.25,
        0
      ],
      'dejavu serif': [
        0.9167,
        0.25,
        0
      ],
      'calibri light': [
        0.9167,
        0.25,
        0
      ]
    };
  var DEVICE_FONT_METRICS_MAC = {
      'al bayan plain': [
        1,
        0.5,
        0
      ],
      'al bayan bold': [
        1,
        0.5833,
        0
      ],
      'american typewriter': [
        0.9167,
        0.25,
        0
      ],
      'american typewriter bold': [
        0.9167,
        0.25,
        0
      ],
      'american typewriter condensed': [
        0.9167,
        0.25,
        0
      ],
      'american typewriter condensed bold': [
        0.9167,
        0.25,
        0
      ],
      'american typewriter condensed light': [
        0.8333,
        0.25,
        0
      ],
      'american typewriter light': [
        0.9167,
        0.25,
        0
      ],
      'andale mono': [
        0.9167,
        0.25,
        0
      ],
      'apple symbols': [
        0.6667,
        0.25,
        0
      ],
      'arial bold italic': [
        0.9167,
        0.25,
        0
      ],
      'arial bold': [
        0.9167,
        0.25,
        0
      ],
      'arial italic': [
        0.9167,
        0.25,
        0
      ],
      'arial hebrew': [
        0.75,
        0.3333,
        0
      ],
      'arial hebrew bold': [
        0.75,
        0.3333,
        0
      ],
      'arial': [
        0.9167,
        0.25,
        0
      ],
      'arial narrow': [
        0.9167,
        0.25,
        0
      ],
      'arial narrow bold': [
        0.9167,
        0.25,
        0
      ],
      'arial narrow bold italic': [
        0.9167,
        0.25,
        0
      ],
      'arial narrow italic': [
        0.9167,
        0.25,
        0
      ],
      'arial rounded mt bold': [
        0.9167,
        0.25,
        0
      ],
      'arial unicode ms': [
        1.0833,
        0.25,
        0
      ],
      'avenir black': [
        1,
        0.3333,
        0
      ],
      'avenir black oblique': [
        1,
        0.3333,
        0
      ],
      'avenir book': [
        1,
        0.3333,
        0
      ],
      'avenir book oblique': [
        1,
        0.3333,
        0
      ],
      'avenir heavy': [
        1,
        0.3333,
        0
      ],
      'avenir heavy oblique': [
        1,
        0.3333,
        0
      ],
      'avenir light': [
        1,
        0.3333,
        0
      ],
      'avenir light oblique': [
        1,
        0.3333,
        0
      ],
      'avenir medium': [
        1,
        0.3333,
        0
      ],
      'avenir medium oblique': [
        1,
        0.3333,
        0
      ],
      'avenir oblique': [
        1,
        0.3333,
        0
      ],
      'avenir roman': [
        1,
        0.3333,
        0
      ],
      'avenir next bold': [
        1,
        0.3333,
        0
      ],
      'avenir next bold italic': [
        1,
        0.3333,
        0
      ],
      'avenir next demi bold': [
        1,
        0.3333,
        0
      ],
      'avenir next demi bold italic': [
        1,
        0.3333,
        0
      ],
      'avenir next heavy': [
        1,
        0.3333,
        0
      ],
      'avenir next heavy italic': [
        1,
        0.3333,
        0
      ],
      'avenir next italic': [
        1,
        0.3333,
        0
      ],
      'avenir next medium': [
        1,
        0.3333,
        0
      ],
      'avenir next medium italic': [
        1,
        0.3333,
        0
      ],
      'avenir next regular': [
        1,
        0.3333,
        0
      ],
      'avenir next ultra light': [
        1,
        0.3333,
        0
      ],
      'avenir next ultra light italic': [
        1,
        0.3333,
        0
      ],
      'avenir next condensed bold': [
        1,
        0.3333,
        0
      ],
      'avenir next condensed bold italic': [
        1,
        0.3333,
        0
      ],
      'avenir next condensed demi bold': [
        1,
        0.3333,
        0
      ],
      'avenir next condensed demi bold italic': [
        1,
        0.3333,
        0
      ],
      'avenir next condensed heavy': [
        1,
        0.3333,
        0
      ],
      'avenir next condensed heavy italic': [
        1,
        0.3333,
        0
      ],
      'avenir next condensed italic': [
        1,
        0.3333,
        0
      ],
      'avenir next condensed medium': [
        1,
        0.3333,
        0
      ],
      'avenir next condensed medium italic': [
        1,
        0.3333,
        0
      ],
      'avenir next condensed regular': [
        1,
        0.3333,
        0
      ],
      'avenir next condensed ultra light': [
        1,
        0.3333,
        0
      ],
      'avenir next condensed ultra light italic': [
        1,
        0.3333,
        0
      ],
      'ayuthaya': [
        1.0833,
        0.3333,
        0
      ],
      'baghdad': [
        0.9167,
        0.4167,
        0
      ],
      'bangla mn': [
        0.9167,
        0.6667,
        0
      ],
      'bangla mn bold': [
        0.9167,
        0.6667,
        0
      ],
      'bangla sangam mn': [
        0.9167,
        0.4167,
        0
      ],
      'bangla sangam mn bold': [
        0.9167,
        0.4167,
        0
      ],
      'baskerville': [
        0.9167,
        0.25,
        0
      ],
      'baskerville bold': [
        0.9167,
        0.25,
        0
      ],
      'baskerville bold italic': [
        0.9167,
        0.25,
        0
      ],
      'baskerville italic': [
        0.9167,
        0.25,
        0
      ],
      'baskerville semibold': [
        0.9167,
        0.25,
        0
      ],
      'baskerville semibold italic': [
        0.9167,
        0.25,
        0
      ],
      'big caslon medium': [
        0.9167,
        0.25,
        0
      ],
      'brush script mt italic': [
        0.9167,
        0.3333,
        0
      ],
      'chalkboard': [
        1,
        0.25,
        0
      ],
      'chalkboard bold': [
        1,
        0.25,
        0
      ],
      'chalkboard se bold': [
        1.1667,
        0.25,
        0
      ],
      'chalkboard se light': [
        1.1667,
        0.25,
        0
      ],
      'chalkboard se regular': [
        1.1667,
        0.25,
        0
      ],
      'chalkduster': [
        1,
        0.25,
        0
      ],
      'charcoal cy': [
        1,
        0.25,
        0
      ],
      'cochin': [
        0.9167,
        0.25,
        0
      ],
      'cochin bold': [
        0.9167,
        0.25,
        0
      ],
      'cochin bold italic': [
        0.9167,
        0.25,
        0
      ],
      'cochin italic': [
        0.9167,
        0.25,
        0
      ],
      'comic sans ms': [
        1.0833,
        0.25,
        0
      ],
      'comic sans ms bold': [
        1.0833,
        0.25,
        0
      ],
      'copperplate': [
        0.75,
        0.25,
        0
      ],
      'copperplate bold': [
        0.75,
        0.25,
        0
      ],
      'copperplate light': [
        0.75,
        0.25,
        0
      ],
      'corsiva hebrew': [
        0.6667,
        0.3333,
        0
      ],
      'corsiva hebrew bold': [
        0.6667,
        0.3333,
        0
      ],
      'courier': [
        0.75,
        0.25,
        0
      ],
      'courier bold': [
        0.75,
        0.25,
        0
      ],
      'courier bold oblique': [
        0.75,
        0.25,
        0
      ],
      'courier oblique': [
        0.75,
        0.25,
        0
      ],
      'courier new bold italic': [
        0.8333,
        0.3333,
        0
      ],
      'courier new bold': [
        0.8333,
        0.3333,
        0
      ],
      'courier new italic': [
        0.8333,
        0.3333,
        0
      ],
      'courier new': [
        0.8333,
        0.3333,
        0
      ],
      'biaukai': [
        0.8333,
        0.1667,
        0
      ],
      'damascus': [
        0.5833,
        0.4167,
        0
      ],
      'damascus bold': [
        0.5833,
        0.4167,
        0
      ],
      'decotype naskh': [
        1.1667,
        0.6667,
        0
      ],
      'devanagari mt': [
        0.9167,
        0.6667,
        0
      ],
      'devanagari mt bold': [
        0.9167,
        0.6667,
        0
      ],
      'devanagari sangam mn': [
        0.9167,
        0.4167,
        0
      ],
      'devanagari sangam mn bold': [
        0.9167,
        0.4167,
        0
      ],
      'didot': [
        0.9167,
        0.3333,
        0
      ],
      'didot bold': [
        1,
        0.3333,
        0
      ],
      'didot italic': [
        0.9167,
        0.25,
        0
      ],
      'euphemia ucas': [
        1.0833,
        0.25,
        0
      ],
      'euphemia ucas bold': [
        1.0833,
        0.25,
        0
      ],
      'euphemia ucas italic': [
        1.0833,
        0.25,
        0
      ],
      'futura condensed extrabold': [
        1,
        0.25,
        0
      ],
      'futura condensed medium': [
        1,
        0.25,
        0
      ],
      'futura medium': [
        1,
        0.25,
        0
      ],
      'futura medium italic': [
        1,
        0.25,
        0
      ],
      'gb18030 bitmap': [
        1,
        0.6667,
        0
      ],
      'geeza pro': [
        0.9167,
        0.3333,
        0
      ],
      'geeza pro bold': [
        0.9167,
        0.3333,
        0
      ],
      'geneva': [
        1,
        0.25,
        0
      ],
      'geneva cy': [
        1,
        0.25,
        0
      ],
      'georgia': [
        0.9167,
        0.25,
        0
      ],
      'georgia bold': [
        0.9167,
        0.25,
        0
      ],
      'georgia bold italic': [
        0.9167,
        0.25,
        0
      ],
      'georgia italic': [
        0.9167,
        0.25,
        0
      ],
      'gill sans': [
        0.9167,
        0.25,
        0
      ],
      'gill sans bold': [
        0.9167,
        0.25,
        0
      ],
      'gill sans bold italic': [
        0.9167,
        0.25,
        0
      ],
      'gill sans italic': [
        0.9167,
        0.25,
        0
      ],
      'gill sans light': [
        0.9167,
        0.25,
        0
      ],
      'gill sans light italic': [
        0.9167,
        0.25,
        0
      ],
      'gujarati mt': [
        0.9167,
        0.6667,
        0
      ],
      'gujarati mt bold': [
        0.9167,
        0.6667,
        0
      ],
      'gujarati sangam mn': [
        0.8333,
        0.4167,
        0
      ],
      'gujarati sangam mn bold': [
        0.8333,
        0.4167,
        0
      ],
      'gurmukhi mn': [
        0.9167,
        0.25,
        0
      ],
      'gurmukhi mn bold': [
        0.9167,
        0.25,
        0
      ],
      'gurmukhi sangam mn': [
        0.9167,
        0.3333,
        0
      ],
      'gurmukhi sangam mn bold': [
        0.9167,
        0.3333,
        0
      ],
      'helvetica': [
        0.75,
        0.25,
        0
      ],
      'helvetica bold': [
        0.75,
        0.25,
        0
      ],
      'helvetica bold oblique': [
        0.75,
        0.25,
        0
      ],
      'helvetica light': [
        0.75,
        0.25,
        0
      ],
      'helvetica light oblique': [
        0.75,
        0.25,
        0
      ],
      'helvetica oblique': [
        0.75,
        0.25,
        0
      ],
      'helvetica neue': [
        0.9167,
        0.25,
        0
      ],
      'helvetica neue bold': [
        1,
        0.25,
        0
      ],
      'helvetica neue bold italic': [
        1,
        0.25,
        0
      ],
      'helvetica neue condensed black': [
        1,
        0.25,
        0
      ],
      'helvetica neue condensed bold': [
        1,
        0.25,
        0
      ],
      'helvetica neue italic': [
        0.9167,
        0.25,
        0
      ],
      'helvetica neue light': [
        1,
        0.25,
        0
      ],
      'helvetica neue light italic': [
        0.9167,
        0.25,
        0
      ],
      'helvetica neue medium': [
        1,
        0.25,
        0
      ],
      'helvetica neue ultralight': [
        0.9167,
        0.25,
        0
      ],
      'helvetica neue ultralight italic': [
        0.9167,
        0.25,
        0
      ],
      'herculanum': [
        0.8333,
        0.1667,
        0
      ],
      'hiragino kaku gothic pro w3': [
        0.9167,
        0.0833,
        0
      ],
      'hiragino kaku gothic pro w6': [
        0.9167,
        0.0833,
        0
      ],
      'hiragino kaku gothic pron w3': [
        0.9167,
        0.0833,
        0
      ],
      'hiragino kaku gothic pron w6': [
        0.9167,
        0.0833,
        0
      ],
      'hiragino kaku gothic std w8': [
        0.9167,
        0.0833,
        0
      ],
      'hiragino kaku gothic stdn w8': [
        0.9167,
        0.0833,
        0
      ],
      'hiragino maru gothic pro w4': [
        0.9167,
        0.0833,
        0
      ],
      'hiragino maru gothic pron w4': [
        0.9167,
        0.0833,
        0
      ],
      'hiragino mincho pro w3': [
        0.9167,
        0.0833,
        0
      ],
      'hiragino mincho pro w6': [
        0.9167,
        0.0833,
        0
      ],
      'hiragino mincho pron w3': [
        0.9167,
        0.0833,
        0
      ],
      'hiragino mincho pron w6': [
        0.9167,
        0.0833,
        0
      ],
      'hiragino sans gb w3': [
        0.9167,
        0.0833,
        0
      ],
      'hiragino sans gb w6': [
        0.9167,
        0.0833,
        0
      ],
      'hoefler text black': [
        0.75,
        0.25,
        0
      ],
      'hoefler text black italic': [
        0.75,
        0.25,
        0
      ],
      'hoefler text italic': [
        0.75,
        0.25,
        0
      ],
      'hoefler text ornaments': [
        0.8333,
        0.1667,
        0
      ],
      'hoefler text': [
        0.75,
        0.25,
        0
      ],
      'impact': [
        1,
        0.25,
        0
      ],
      'inaimathi': [
        0.8333,
        0.4167,
        0
      ],
      'headlinea regular': [
        0.8333,
        0.1667,
        0
      ],
      'pilgi regular': [
        0.8333,
        0.25,
        0
      ],
      'gungseo regular': [
        0.8333,
        0.25,
        0
      ],
      'pcmyungjo regular': [
        0.8333,
        0.25,
        0
      ],
      'kailasa regular': [
        1.0833,
        0.5833,
        0
      ],
      'kannada mn': [
        0.9167,
        0.25,
        0
      ],
      'kannada mn bold': [
        0.9167,
        0.25,
        0
      ],
      'kannada sangam mn': [
        1,
        0.5833,
        0
      ],
      'kannada sangam mn bold': [
        1,
        0.5833,
        0
      ],
      'kefa bold': [
        0.9167,
        0.25,
        0
      ],
      'kefa regular': [
        0.9167,
        0.25,
        0
      ],
      'khmer mn': [
        1,
        0.6667,
        0
      ],
      'khmer mn bold': [
        1,
        0.6667,
        0
      ],
      'khmer sangam mn': [
        1.0833,
        0.6667,
        0
      ],
      'kokonor regular': [
        1.0833,
        0.5833,
        0
      ],
      'krungthep': [
        1,
        0.25,
        0
      ],
      'kufistandardgk': [
        0.9167,
        0.5,
        0
      ],
      'lao mn': [
        0.9167,
        0.4167,
        0
      ],
      'lao mn bold': [
        0.9167,
        0.4167,
        0
      ],
      'lao sangam mn': [
        1,
        0.3333,
        0
      ],
      'apple ligothic medium': [
        0.8333,
        0.1667,
        0
      ],
      'lihei pro': [
        0.8333,
        0.1667,
        0
      ],
      'lisong pro': [
        0.8333,
        0.1667,
        0
      ],
      'lucida grande': [
        1,
        0.25,
        0
      ],
      'lucida grande bold': [
        1,
        0.25,
        0
      ],
      'malayalam mn': [
        1,
        0.4167,
        0
      ],
      'malayalam mn bold': [
        1,
        0.4167,
        0
      ],
      'malayalam sangam mn': [
        0.8333,
        0.4167,
        0
      ],
      'malayalam sangam mn bold': [
        0.8333,
        0.4167,
        0
      ],
      'marion bold': [
        0.6667,
        0.3333,
        0
      ],
      'marion italic': [
        0.6667,
        0.3333,
        0
      ],
      'marion regular': [
        0.6667,
        0.3333,
        0
      ],
      'marker felt thin': [
        0.8333,
        0.25,
        0
      ],
      'marker felt wide': [
        0.9167,
        0.25,
        0
      ],
      'menlo bold': [
        0.9167,
        0.25,
        0
      ],
      'menlo bold italic': [
        0.9167,
        0.25,
        0
      ],
      'menlo italic': [
        0.9167,
        0.25,
        0
      ],
      'menlo regular': [
        0.9167,
        0.25,
        0
      ],
      'microsoft sans serif': [
        0.9167,
        0.25,
        0
      ],
      'monaco': [
        1,
        0.25,
        0
      ],
      'gurmukhi mt': [
        0.8333,
        0.4167,
        0
      ],
      'mshtakan': [
        0.9167,
        0.25,
        0
      ],
      'mshtakan bold': [
        0.9167,
        0.25,
        0
      ],
      'mshtakan boldoblique': [
        0.9167,
        0.25,
        0
      ],
      'mshtakan oblique': [
        0.9167,
        0.25,
        0
      ],
      'myanmar mn': [
        1,
        0.4167,
        0
      ],
      'myanmar mn bold': [
        1,
        0.4167,
        0
      ],
      'myanmar sangam mn': [
        0.9167,
        0.4167,
        0
      ],
      'nadeem': [
        0.9167,
        0.4167,
        0
      ],
      'nanum brush script': [
        0.9167,
        0.25,
        0
      ],
      'nanumgothic': [
        0.9167,
        0.25,
        0
      ],
      'nanumgothic bold': [
        0.9167,
        0.25,
        0
      ],
      'nanumgothic extrabold': [
        0.9167,
        0.25,
        0
      ],
      'nanummyeongjo': [
        0.9167,
        0.25,
        0
      ],
      'nanummyeongjo bold': [
        0.9167,
        0.25,
        0
      ],
      'nanummyeongjo extrabold': [
        0.9167,
        0.25,
        0
      ],
      'nanum pen script': [
        0.9167,
        0.25,
        0
      ],
      'optima bold': [
        0.9167,
        0.25,
        0
      ],
      'optima bold italic': [
        0.9167,
        0.25,
        0
      ],
      'optima extrablack': [
        1,
        0.25,
        0
      ],
      'optima italic': [
        0.9167,
        0.25,
        0
      ],
      'optima regular': [
        0.9167,
        0.25,
        0
      ],
      'oriya mn': [
        0.9167,
        0.25,
        0
      ],
      'oriya mn bold': [
        0.9167,
        0.25,
        0
      ],
      'oriya sangam mn': [
        0.8333,
        0.4167,
        0
      ],
      'oriya sangam mn bold': [
        0.8333,
        0.4167,
        0
      ],
      'osaka': [
        1,
        0.25,
        0
      ],
      'osaka-mono': [
        0.8333,
        0.1667,
        0
      ],
      'palatino bold': [
        0.8333,
        0.25,
        0
      ],
      'palatino bold italic': [
        0.8333,
        0.25,
        0
      ],
      'palatino italic': [
        0.8333,
        0.25,
        0
      ],
      'palatino': [
        0.8333,
        0.25,
        0
      ],
      'papyrus': [
        0.9167,
        0.5833,
        0
      ],
      'papyrus condensed': [
        0.9167,
        0.5833,
        0
      ],
      'plantagenet cherokee': [
        0.6667,
        0.25,
        0
      ],
      'raanana': [
        0.75,
        0.25,
        0
      ],
      'raanana bold': [
        0.75,
        0.25,
        0
      ],
      'hei regular': [
        0.8333,
        0.1667,
        0
      ],
      'kai regular': [
        0.8333,
        0.1667,
        0
      ],
      'stfangsong': [
        0.8333,
        0.1667,
        0
      ],
      'stheiti': [
        0.8333,
        0.1667,
        0
      ],
      'heiti sc light': [
        0.8333,
        0.1667,
        0
      ],
      'heiti sc medium': [
        0.8333,
        0.1667,
        0
      ],
      'heiti tc light': [
        0.8333,
        0.1667,
        0
      ],
      'heiti tc medium': [
        0.8333,
        0.1667,
        0
      ],
      'stkaiti': [
        0.8333,
        0.1667,
        0
      ],
      'kaiti sc black': [
        1.0833,
        0.3333,
        0
      ],
      'kaiti sc bold': [
        1.0833,
        0.3333,
        0
      ],
      'kaiti sc regular': [
        1.0833,
        0.3333,
        0
      ],
      'stsong': [
        0.8333,
        0.1667,
        0
      ],
      'songti sc black': [
        1.0833,
        0.3333,
        0
      ],
      'songti sc bold': [
        1.0833,
        0.3333,
        0
      ],
      'songti sc light': [
        1.0833,
        0.3333,
        0
      ],
      'songti sc regular': [
        1.0833,
        0.3333,
        0
      ],
      'stxihei': [
        0.8333,
        0.1667,
        0
      ],
      'sathu': [
        0.9167,
        0.3333,
        0
      ],
      'silom': [
        1,
        0.3333,
        0
      ],
      'sinhala mn': [
        0.9167,
        0.25,
        0
      ],
      'sinhala mn bold': [
        0.9167,
        0.25,
        0
      ],
      'sinhala sangam mn': [
        1.1667,
        0.3333,
        0
      ],
      'sinhala sangam mn bold': [
        1.1667,
        0.3333,
        0
      ],
      'skia regular': [
        0.75,
        0.25,
        0
      ],
      'symbol': [
        0.6667,
        0.3333,
        0
      ],
      'tahoma negreta': [
        1,
        0.1667,
        0
      ],
      'tamil mn': [
        0.9167,
        0.25,
        0
      ],
      'tamil mn bold': [
        0.9167,
        0.25,
        0
      ],
      'tamil sangam mn': [
        0.75,
        0.25,
        0
      ],
      'tamil sangam mn bold': [
        0.75,
        0.25,
        0
      ],
      'telugu mn': [
        0.9167,
        0.25,
        0
      ],
      'telugu mn bold': [
        0.9167,
        0.25,
        0
      ],
      'telugu sangam mn': [
        1,
        0.5833,
        0
      ],
      'telugu sangam mn bold': [
        1,
        0.5833,
        0
      ],
      'thonburi': [
        1.0833,
        0.25,
        0
      ],
      'thonburi bold': [
        1.0833,
        0.25,
        0
      ],
      'times bold': [
        0.75,
        0.25,
        0
      ],
      'times bold italic': [
        0.75,
        0.25,
        0
      ],
      'times italic': [
        0.75,
        0.25,
        0
      ],
      'times roman': [
        0.75,
        0.25,
        0
      ],
      'times new roman bold italic': [
        0.9167,
        0.25,
        0
      ],
      'times new roman bold': [
        0.9167,
        0.25,
        0
      ],
      'times new roman italic': [
        0.9167,
        0.25,
        0
      ],
      'times new roman': [
        0.9167,
        0.25,
        0
      ],
      'trebuchet ms bold italic': [
        0.9167,
        0.25,
        0
      ],
      'trebuchet ms': [
        0.9167,
        0.25,
        0
      ],
      'trebuchet ms bold': [
        0.9167,
        0.25,
        0
      ],
      'trebuchet ms italic': [
        0.9167,
        0.25,
        0
      ],
      'verdana': [
        1,
        0.25,
        0
      ],
      'verdana bold': [
        1,
        0.25,
        0
      ],
      'verdana bold italic': [
        1,
        0.25,
        0
      ],
      'verdana italic': [
        1,
        0.25,
        0
      ],
      'webdings': [
        0.8333,
        0.1667,
        0
      ],
      'wingdings 2': [
        0.8333,
        0.25,
        0
      ],
      'wingdings 3': [
        0.9167,
        0.25,
        0
      ],
      'yuppy sc regular': [
        1.0833,
        0.3333,
        0
      ],
      'yuppy tc regular': [
        1.0833,
        0.3333,
        0
      ],
      'zapf dingbats': [
        0.8333,
        0.1667,
        0
      ],
      'zapfino': [
        1.9167,
        1.5,
        0
      ]
    };
  var DEVICE_FONT_METRICS_LINUX = {
      'kacstfarsi': [
        1.0831,
        0.5215,
        0
      ],
      'meera': [
        0.682,
        0.4413,
        0
      ],
      'freemono': [
        0.8023,
        0.2006,
        0
      ],
      'undotum': [
        1.0029,
        0.2808,
        0
      ],
      'loma': [
        1.1634,
        0.4814,
        0
      ],
      'century schoolbook l': [
        1.0029,
        0.3209,
        0
      ],
      'kacsttitlel': [
        1.0831,
        0.5215,
        0
      ],
      'undinaru': [
        1.0029,
        0.2407,
        0
      ],
      'ungungseo': [
        1.0029,
        0.2808,
        0
      ],
      'garuda': [
        1.3238,
        0.6017,
        0
      ],
      'rekha': [
        1.1232,
        0.2808,
        0
      ],
      'purisa': [
        1.1232,
        0.5215,
        0
      ],
      'dejavu sans mono': [
        0.9628,
        0.2407,
        0
      ],
      'vemana2000': [
        0.8825,
        0.8424,
        0
      ],
      'kacstoffice': [
        1.0831,
        0.5215,
        0
      ],
      'umpush': [
        1.2837,
        0.682,
        0
      ],
      'opensymbol': [
        0.8023,
        0.2006,
        0
      ],
      'sawasdee': [
        1.1232,
        0.4413,
        0
      ],
      'urw palladio l': [
        1.0029,
        0.3209,
        0
      ],
      'freeserif': [
        0.9227,
        0.3209,
        0
      ],
      'kacstdigital': [
        1.0831,
        0.5215,
        0
      ],
      'ubuntu condensed': [
        0.9628,
        0.2006,
        0
      ],
      'unpilgi': [
        1.0029,
        0.4413,
        0
      ],
      'mry_kacstqurn': [
        1.4442,
        0.7221,
        0
      ],
      'urw gothic l': [
        1.0029,
        0.2407,
        0
      ],
      'dingbats': [
        0.8424,
        0.1605,
        0
      ],
      'urw chancery l': [
        1.0029,
        0.3209,
        0
      ],
      'phetsarath ot': [
        1.0831,
        0.5215,
        0
      ],
      'tlwg typist': [
        0.8825,
        0.4012,
        0
      ],
      'kacstletter': [
        1.0831,
        0.5215,
        0
      ],
      'utkal': [
        1.2035,
        0.6418,
        0
      ],
      'dejavu sans light': [
        0.9628,
        0.2407,
        0
      ],
      'norasi': [
        1.2436,
        0.5215,
        0
      ],
      'dejavu serif condensed': [
        0.9628,
        0.2407,
        0
      ],
      'kacstone': [
        1.2436,
        0.6418,
        0
      ],
      'liberation sans narrow': [
        0.9628,
        0.2407,
        0
      ],
      'symbol': [
        1.043,
        0.3209,
        0
      ],
      'nanummyeongjo': [
        0.9227,
        0.2407,
        0
      ],
      'untitled1': [
        0.682,
        0.5616,
        0
      ],
      'lohit gujarati': [
        0.9628,
        0.4012,
        0
      ],
      'liberation mono': [
        0.8424,
        0.3209,
        0
      ],
      'kacstart': [
        1.0831,
        0.5215,
        0
      ],
      'mallige': [
        1.0029,
        0.682,
        0
      ],
      'bitstream charter': [
        1.0029,
        0.2407,
        0
      ],
      'nanumgothic': [
        0.9227,
        0.2407,
        0
      ],
      'liberation serif': [
        0.9227,
        0.2407,
        0
      ],
      'dejavu sans condensed': [
        0.9628,
        0.2407,
        0
      ],
      'ubuntu': [
        0.9628,
        0.2006,
        0
      ],
      'courier 10 pitch': [
        0.8825,
        0.3209,
        0
      ],
      'nimbus sans l': [
        0.9628,
        0.3209,
        0
      ],
      'takaopgothic': [
        0.8825,
        0.2006,
        0
      ],
      'wenquanyi micro hei mono': [
        0.9628,
        0.2407,
        0
      ],
      'dejavu sans': [
        0.9628,
        0.2407,
        0
      ],
      'kedage': [
        1.0029,
        0.682,
        0
      ],
      'kinnari': [
        1.3238,
        0.5215,
        0
      ],
      'tlwgmono': [
        0.8825,
        0.4012,
        0
      ],
      'standard symbols l': [
        1.043,
        0.3209,
        0
      ],
      'lohit punjabi': [
        1.2035,
        0.682,
        0
      ],
      'nimbus mono l': [
        0.8424,
        0.2808,
        0
      ],
      'rachana': [
        0.682,
        0.5616,
        0
      ],
      'waree': [
        1.2436,
        0.4413,
        0
      ],
      'kacstposter': [
        1.0831,
        0.5215,
        0
      ],
      'khmer os': [
        1.2837,
        0.7622,
        0
      ],
      'freesans': [
        1.0029,
        0.3209,
        0
      ],
      'gargi': [
        0.9628,
        0.2808,
        0
      ],
      'nimbus roman no9 l': [
        0.9628,
        0.3209,
        0
      ],
      'dejavu serif': [
        0.9628,
        0.2407,
        0
      ],
      'wenquanyi micro hei': [
        0.9628,
        0.2407,
        0
      ],
      'ubuntu light': [
        0.9628,
        0.2006,
        0
      ],
      'tlwgtypewriter': [
        0.9227,
        0.4012,
        0
      ],
      'kacstpen': [
        1.0831,
        0.5215,
        0
      ],
      'tlwg typo': [
        0.8825,
        0.4012,
        0
      ],
      'mukti narrow': [
        1.2837,
        0.4413,
        0
      ],
      'ubuntu mono': [
        0.8424,
        0.2006,
        0
      ],
      'lohit bengali': [
        1.0029,
        0.4413,
        0
      ],
      'liberation sans': [
        0.9227,
        0.2407,
        0
      ],
      'unbatang': [
        1.0029,
        0.2808,
        0
      ],
      'kacstdecorative': [
        1.1232,
        0.5215,
        0
      ],
      'khmer os system': [
        1.2436,
        0.6017,
        0
      ],
      'saab': [
        1.0029,
        0.682,
        0
      ],
      'kacsttitle': [
        1.0831,
        0.5215,
        0
      ],
      'mukti narrow bold': [
        1.2837,
        0.4413,
        0
      ],
      'lohit hindi': [
        1.0029,
        0.5215,
        0
      ],
      'kacstqurn': [
        1.0831,
        0.5215,
        0
      ],
      'urw bookman l': [
        0.9628,
        0.2808,
        0
      ],
      'kacstnaskh': [
        1.0831,
        0.5215,
        0
      ],
      'kacstscreen': [
        1.0831,
        0.5215,
        0
      ],
      'pothana2000': [
        0.8825,
        0.8424,
        0
      ],
      'ungraphic': [
        1.0029,
        0.2808,
        0
      ],
      'lohit tamil': [
        0.8825,
        0.361,
        0
      ],
      'kacstbook': [
        1.0831,
        0.5215,
        0
      ]
    };
  DEVICE_FONT_METRICS_MAC.__proto__ = DEVICE_FONT_METRICS_WIN;
  DEVICE_FONT_METRICS_LINUX.__proto__ = DEVICE_FONT_METRICS_MAC;
}
var StaticTextDefinition = function () {
    var def = {
        __class__: 'flash.text.StaticText',
        initialize: function () {
          var s = this.symbol;
          if (s) {
            this.draw = s.draw;
          }
        },
        get text() {
          return this._text;
        },
        set text(val) {
          this._text = val;
        }
      };
    var desc = Object.getOwnPropertyDescriptor;
    def.__glue__ = {
      native: {
        instance: {
          text: desc(def, 'text')
        }
      }
    };
    return def;
  }.call(this);
var StyleSheetDefinition = function () {
    return {
      __class__: 'flash.text.StyleSheet',
      initialize: function () {
      },
      __glue__: {
        native: {
          static: {},
          instance: {
            _update: function _update() {
              somewhatImplemented('StyleSheet._update');
            },
            _parseCSSInternal: function _parseCSSInternal(cssText) {
              somewhatImplemented('StyleSheet._parseCSSInternal');
              return null;
            },
            _parseCSSFontFamily: function _parseCSSFontFamily(fontFamily) {
              notImplemented('StyleSheet._parseCSSFontFamily');
            },
            _parseColor: function _parseColor(color) {
              notImplemented('StyleSheet._parseColor');
            },
            _styles: {
              get: function _styles() {
                return this.__styles;
              },
              set: function _styles(styles) {
                somewhatImplemented('StyleSheet._styles');
                this.__styles = styles;
              }
            }
          }
        }
      }
    };
  }.call(this);
var TextFieldDefinition = function () {
    var def = {
        __class__: 'flash.text.TextField',
        initialize: function () {
          this._bbox = {
            xMin: 0,
            yMin: 0,
            xMax: 2000,
            yMax: 2000
          };
          var initialFormat = {
              align: 'LEFT',
              face: 'serif',
              size: 12,
              letterspacing: 0,
              kerning: 0,
              color: 0,
              leading: 0
            };
          this._content = new TextFieldContent(initialFormat);
          this._type = 'dynamic';
          this._embedFonts = false;
          this._selectable = true;
          this._autoSize = 'none';
          this._scrollV = 1;
          this._maxScrollV = 1;
          this._bottomScrollV = 1;
          this._drawingOffsetH = 0;
          this._background = false;
          this._border = false;
          this._backgroundColor = 16777215;
          this._backgroundColorStr = '#ffffff';
          this._borderColor = 0;
          this._borderColorStr = '#000000';
          var s = this.symbol;
          if (!s) {
            this._currentTransform.tx -= 40;
            this._currentTransform.ty -= 40;
            this._content.resolveFont(initialFormat, false);
            this.text = '';
            return;
          }
          var tag = s.tag;
          var bbox = tag.bbox;
          this._currentTransform.tx += bbox.xMin;
          this._currentTransform.ty += bbox.yMin;
          this._bbox.xMax = bbox.xMax - bbox.xMin;
          this._bbox.yMax = bbox.yMax - bbox.yMin;
          if (tag.hasLayout) {
            initialFormat.size = tag.fontHeight / 20;
            initialFormat.leading = (tag.leading | 0) / 20;
          }
          if (tag.hasColor) {
            initialFormat.color = rgbaObjToStr(tag.color);
          }
          if (tag.hasFont) {
            var font = FontDefinition.getFontByUniqueName(tag.font);
            initialFormat.font = font;
            initialFormat.face = font._fontName;
            initialFormat.bold = font.symbol.bold;
            initialFormat.italic = font.symbol.italic;
            initialFormat.str = this._content.makeFormatString(initialFormat);
          }
          this._content.multiline = !(!tag.multiline);
          this._content.wordWrap = !(!tag.wordWrap);
          this._embedFonts = !(!tag.useOutlines);
          this._selectable = !tag.noSelect;
          this._border = !(!tag.border);
          switch (tag.align) {
          case 1:
            initialFormat.align = 'right';
            break;
          case 2:
            initialFormat.align = 'center';
            break;
          case 3:
            initialFormat.align = 'justified';
            break;
          default:
          }
          if (tag.initialText) {
            if (tag.html) {
              this.htmlText = tag.initialText;
            } else {
              this.text = tag.initialText;
            }
          } else {
            this.text = '';
          }
        },
        _getAS2Object: function () {
          if (!this.$as2Object) {
            new avm1lib.AS2TextField(this);
          }
          return this.$as2Object;
        },
        replaceText: function (begin, end, str) {
          var text = this._content.text;
          this.text = text.substring(0, begin) + str + text.substring(end);
        },
        draw: function (ctx, ratio, colorTransform) {
          this.ensureDimensions();
          var bounds = this._bbox;
          var width = bounds.xMax / 20;
          var height = bounds.yMax / 20;
          if (width <= 0 || height <= 0) {
            return;
          }
          ctx.save();
          ctx.beginPath();
          ctx.rect(0, 0, width + 1, height + 1);
          ctx.clip();
          if (this._background) {
            colorTransform.setFillStyle(ctx, this._backgroundColorStr);
            ctx.fill();
          }
          if (this._border) {
            colorTransform.setStrokeStyle(ctx, this._borderColorStr);
            ctx.lineCap = 'square';
            ctx.lineWidth = 1;
            ctx.strokeRect(0.5, 0.5, width | 0, height | 0);
          }
          ctx.closePath();
          if (this._content.lines.length === 0) {
            ctx.restore();
            return;
          }
          ctx.translate(2, 2);
          ctx.save();
          colorTransform.setAlpha(ctx);
          var runs = this._content._textRuns;
          var offsetY = this._content.lines[this._scrollV - 1].y;
          for (var i = 0; i < runs.length; i++) {
            var run = runs[i];
            if (run.type === 'f') {
              ctx.restore();
              ctx.font = run.format.str;
              colorTransform.setFillStyle(ctx, run.format.color);
              ctx.save();
              colorTransform.setAlpha(ctx);
            } else {
              if (run.y < offsetY) {
                continue;
              }
              ctx.fillText(run.text, run.x - this._drawingOffsetH, run.y - offsetY);
            }
          }
          ctx.restore();
          ctx.restore();
        },
        invalidateDimensions: function () {
          this._invalidate();
          this._invalidateBounds();
          this._dimensionsValid = false;
        },
        ensureDimensions: function () {
          if (this._dimensionsValid) {
            return;
          }
          var bounds = this._bbox;
          var combinedAlign = this._content.calculateMetrics(bounds, this._embedFonts);
          this._scrollV = 1;
          this._maxScrollV = 1;
          this._bottomScrollV = 1;
          var autoSize = this._autoSize;
          if (autoSize === 'none') {
            var maxVisibleY = (bounds.yMax - 80) / 20;
            if (this._content.textHeight > maxVisibleY) {
              var lines = this._content.lines;
              for (var i = 0; i < lines.length; i++) {
                var line = lines[i];
                if (line.y + line.height > maxVisibleY) {
                  this._maxScrollV = i + 1;
                  this._bottomScrollV = i === 0 ? 1 : i;
                  break;
                }
              }
            }
          } else {
            var width = Math.max(bounds.xMax / 20 - 4, 1);
            var targetWidth = this._content.textWidth;
            var align = combinedAlign;
            var diffX = 0;
            if (align !== 'mixed') {
              switch (autoSize) {
              case 'left':
                break;
              case 'center':
                diffX = width - targetWidth >> 1;
                break;
              case 'right':
                diffX = width - targetWidth;
              }
              if (align === 'left') {
                this._drawingOffsetH = 0;
              } else {
                var offset;
                switch (autoSize) {
                case 'left':
                  offset = width - targetWidth;
                  break;
                case 'center':
                  offset = diffX << 1;
                  break;
                case 'right':
                  offset = diffX;
                  break;
                }
                if (align === 'center') {
                  offset >>= 1;
                }
                this._drawingOffsetH = offset;
              }
              this._invalidateTransform();
              this._currentTransform.tx += diffX * 20 | 0;
              bounds.xMax = (targetWidth * 20 | 0) + 80;
            }
            bounds.yMax = (this._content.textHeight * 20 | 0) + 80;
            console.log(bounds.yMax);
            this._invalidateBounds();
          }
          this._dimensionsValid = true;
        },
        get text() {
          return this._content.text;
        },
        set text(val) {
          this._content.text = val;
          this.invalidateDimensions();
        },
        get htmlText() {
          return this._content.htmlText;
        },
        set htmlText(val) {
          this._content.htmlText = val;
          this.invalidateDimensions();
        },
        get defaultTextFormat() {
          var format = this._content.defaultTextFormat;
          return new flash.text.TextFormat().fromObject(format);
        },
        set defaultTextFormat(val) {
          this._content.defaultTextFormat = val.toObject();
          this.invalidateDimensions();
        },
        getTextFormat: function (beginIndex, endIndex) {
          return this.defaultTextFormat;
        },
        setTextFormat: function (format, beginIndex, endIndex) {
          this.defaultTextFormat = format;
          if (this.text === this.htmlText) {
            this.text = this.text;
          }
          this.invalidateDimensions();
        },
        get x() {
          this.ensureDimensions();
          return this._currentTransform.tx;
        },
        set x(val) {
          if (val === this._currentTransform.tx) {
            return;
          }
          this._invalidate();
          this._invalidateBounds();
          this._invalidateTransform();
          this._currentTransform.tx = val;
        },
        get width() {
          this.ensureDimensions();
          return this._bbox.xMax;
        },
        set width(value) {
          if (value < 0) {
            return;
          }
          this._bbox.xMax = value;
          this.invalidateDimensions();
        },
        get height() {
          this.ensureDimensions();
          return this._bbox.yMax;
        },
        set height(value) {
          if (value < 0) {
            return;
          }
          this._bbox.yMax = value;
          this._invalidate();
        },
        _getContentBounds: function () {
          this.ensureDimensions();
          return this._bbox;
        },
        _getRegion: function getRegion(targetCoordSpace) {
          return this._getTransformedRect(this._getContentBounds(), targetCoordSpace);
        },
        getLineMetrics: function (lineIndex) {
          this.ensureDimensions();
          if (lineIndex < 0 || lineIndex >= this._content.lines.length) {
            throwError('RangeError', Errors.ParamRangeError);
          }
          var line = this._content.lines[lineIndex];
          var format = line.largestFormat;
          var metrics = format.font._metrics;
          var size = format.size;
          var ascent = metrics.ascent * size + 0.49999 | 0;
          var descent = metrics.descent * size + 0.49999 | 0;
          var leading = metrics.leading * size + 0.49999 + line.leading | 0;
          return new flash.text.TextLineMetrics(line.x + 2, line.width, line.height, ascent, descent, leading);
        },
        getCharBoundaries: function getCharBoundaries(index) {
          somewhatImplemented('TextField.getCharBoundaries');
          return new flash.geom.Rectangle(0, 0, 0, 0);
        }
      };
    var desc = Object.getOwnPropertyDescriptor;
    def.__glue__ = {
      native: {
        instance: {
          text: desc(def, 'text'),
          defaultTextFormat: desc(def, 'defaultTextFormat'),
          draw: def.draw,
          htmlText: desc(def, 'htmlText'),
          replaceText: def.replaceText,
          getTextFormat: def.getTextFormat,
          setTextFormat: def.setTextFormat,
          getCharBoundaries: def.getCharBoundaries,
          autoSize: {
            get: function autoSize() {
              return this._autoSize;
            },
            set: function autoSize(value) {
              if (this._autoSize === value) {
                return;
              }
              this._autoSize = value;
              this.invalidateDimensions();
            }
          },
          multiline: {
            get: function multiline() {
              return this._content.multiline;
            },
            set: function multiline(value) {
              if (this._content.multiline === value) {
                return;
              }
              this._content.multiline = value;
              this.invalidateDimensions();
            }
          },
          textColor: {
            get: function textColor() {
              return this._content.textColor;
            },
            set: function textColor(value) {
              if (this._content.textColor === value) {
                return;
              }
              this._content.textColor = value;
              this._invalidate();
            }
          },
          selectable: {
            get: function selectable() {
              return this._selectable;
            },
            set: function selectable(value) {
              somewhatImplemented('TextField.selectable');
              this._selectable = value;
            }
          },
          wordWrap: {
            get: function wordWrap() {
              return this._content.wordWrap;
            },
            set: function wordWrap(value) {
              if (this._content.wordWrap === value) {
                return;
              }
              this._content.wordWrap = value;
              this.invalidateDimensions();
            }
          },
          textHeight: {
            get: function textHeight() {
              this.ensureDimensions();
              return this._content.textHeight;
            }
          },
          textWidth: {
            get: function textWidth() {
              this.ensureDimensions();
              return this._content.textWidth;
            }
          },
          length: {
            get: function length() {
              return this.text.length;
            }
          },
          numLines: {
            get: function numLines() {
              this.ensureDimensions();
              return this._content.lines.length;
            }
          },
          getLineMetrics: function (lineIndex) {
            return this.getLineMetrics(lineIndex);
          },
          setSelection: function (beginIndex, endIndex) {
            somewhatImplemented('TextField.setSelection');
          },
          scrollV: {
            get: function scrollV() {
              return this._scrollV;
            },
            set: function scrollV(value) {
              this.ensureDimensions();
              value = Math.max(1, Math.min(this._maxScrollV, value));
              this._scrollV = value;
            }
          },
          bottomScrollV: {
            get: function bottomScrollV() {
              this.ensureDimensions();
              if (this._scrollV === 1) {
                return this._bottomScrollV;
              }
              var maxVisibleY = (this._bbox.yMax - 80) / 20;
              var lines = this._content.lines;
              var offsetY = lines[this._scrollV - 1].y;
              for (var i = this._bottomScrollV; i < lines.length; i++) {
                var line = lines[i];
                if (line.y + line.height + offsetY > maxVisibleY) {
                  return i + 1;
                }
              }
            }
          },
          maxScrollV: {
            get: function maxScrollV() {
              this.ensureDimensions();
              return this._maxScrollV;
            }
          },
          maxScrollH: {
            get: function maxScrollH() {
              this.ensureDimensions();
              return Math.max(this._content.textWidth - this._bbox.xMax / 20 + 4, 0);
            }
          },
          background: {
            get: function background() {
              return this._background;
            },
            set: function background(value) {
              if (this._background === value) {
                return;
              }
              this._background = value;
              this._invalidate();
            }
          },
          backgroundColor: {
            get: function backgroundColor() {
              return this._backgroundColor;
            },
            set: function backgroundColor(value) {
              if (this._backgroundColor === value) {
                return;
              }
              this._backgroundColor = value;
              this._backgroundColorStr = rgbIntAlphaToStr(value, 1);
              if (this._background) {
                this._invalidate();
              }
            }
          },
          border: {
            get: function border() {
              return this._border;
            },
            set: function border(value) {
              if (this._border === value) {
                return;
              }
              this._border = value;
              this._invalidate();
            }
          },
          borderColor: {
            get: function borderColor() {
              return this._borderColor;
            },
            set: function borderColor(value) {
              if (this._borderColor === value) {
                return;
              }
              this._borderColor = value;
              this._borderColorStr = rgbIntAlphaToStr(value, 1);
              if (this._border) {
                this._invalidate();
              }
            }
          },
          type: {
            get: function borderColor() {
              return this._type;
            },
            set: function borderColor(value) {
              somewhatImplemented('TextField.type');
              this._type = value;
            }
          },
          embedFonts: {
            get: function embedFonts() {
              return this._embedFonts;
            },
            set: function embedFonts(value) {
              this.invalidateDimensions();
              this._embedFonts = value;
            }
          },
          condenseWhite: {
            get: function condenseWhite() {
              return this._content.condenseWhite;
            },
            set: function condenseWhite(value) {
              somewhatImplemented('TextField.condenseWhite');
              this._content.condenseWhite = value;
            }
          },
          sharpness: {
            get: function sharpness() {
              return this._sharpness;
            },
            set: function sharpness(value) {
              somewhatImplemented('TextField.sharpness');
              this._sharpness = value;
            }
          }
        }
      }
    };
    return def;
  }.call(this);
function TextFieldContent(initialFormat) {
  this.defaultTextFormat = initialFormat;
  this.textWidth = 0;
  this.textHeight = 0;
  this.condenseWhite = false;
  this.wordWrap = false;
  this.multiline = false;
  this.textColor = null;
  this._text = '';
  this._htmlText = '';
  this._createTrunk();
  this._textRuns = null;
  this._htmlParser = document.createElement('p');
  this._measureCtx = document.createElement('canvas').getContext('2d');
}
TextFieldContent.knownNodeTypes = {
  'BR': true,
  'LI': true,
  'P': true,
  'B': true,
  'I': true,
  'FONT': true,
  'TEXTFORMAT': true,
  'U': true,
  'A': true,
  'IMG': true,
  'SPAN': true
};
TextFieldContent.WRAP_OPPORTUNITIES = {
  ' ': true,
  '.': true,
  '-': true,
  '\t': true
};
TextFieldContent.TextLine = function (y) {
  this.x = 0;
  this.width = 0;
  this.y = y;
  this.height = 0;
  this.leading = 0;
  this.runs = [];
  this.largestFormat = null;
};
TextFieldContent.prototype = {
  get text() {
    return this._text;
  },
  set text(val) {
    val = val + '';
    if (this._text === val) {
      return;
    }
    var lines = [];
    var lineOffset = 0;
    for (var index = 0; index < val.length;) {
      var char = val[index];
      if (char === '\r' || char === '\n') {
        lines.push(val.substring(lineOffset, index));
        lineOffset = index;
        if (char === '\r' && val[index + 1] === '\n') {
          index++;
        }
      }
      index++;
    }
    lines.push(val.substring(lineOffset, index));
    this._createTrunk();
    this._text = val;
    this._htmlText = val;
    this._tree.children[0].children[0] = {
      type: 'plain-text',
      lines: lines
    };
  },
  get htmlText() {
    return this._htmlText;
  },
  set htmlText(val) {
    if (this._htmlText === val) {
      return;
    }
    this.defaultTextFormat.bold = false;
    this.defaultTextFormat.italic = false;
    this._parseHtml(val);
  },
  calculateMetrics: function (bounds, embedFonts) {
    var initialFormat = this.defaultTextFormat;
    this.resolveFont(initialFormat, embedFonts);
    this.lines = [];
    this._textRuns = [
      {
        type: 'f',
        format: initialFormat
      }
    ];
    var width = Math.max(bounds.xMax / 20 - 4, 1);
    var height = Math.max(bounds.yMax / 20 - 4, 1);
    var state = {
        ctx: this._measureCtx,
        w: width,
        h: height,
        maxLineWidth: 0,
        formats: [
          initialFormat
        ],
        currentFormat: initialFormat,
        line: new TextFieldContent.TextLine(0),
        wordWrap: this.wordWrap,
        combinedAlign: null,
        textColor: this.textColor,
        embedFonts: embedFonts
      };
    this._collectRuns(state, this._tree);
    this._finishLine(state, false);
    this.textWidth = state.maxLineWidth | 0;
    this.textHeight = state.line.y | 0;
    return state.combinedAlign;
  },
  makeFormatString: function (format) {
    var boldItalic = '';
    if (format.italic) {
      boldItalic += 'italic';
    }
    if (format.bold) {
      boldItalic += ' bold';
    }
    return boldItalic + ' ' + format.size + 'px ' + (format.font._uniqueName || format.font._fontName);
  },
  resolveFont: function (format, embedded) {
    var face = format.face.toLowerCase();
    if (face === '_sans') {
      face = 'sans-serif';
    } else if (face === '_serif') {
      face = 'serif';
    } else if (face === '_typewriter') {
      face = 'monospace';
    }
    var style;
    if (format.bold) {
      if (format.italic) {
        style = 'boldItalic';
      } else {
        style = 'bold';
      }
    } else if (format.italic) {
      style = 'italic';
    } else {
      style = 'regular';
    }
    var font = FontDefinition.getFont(face, style, embedded);
    format.font = font;
  },
  _parseHtml: function (val) {
    this._htmlParser.innerHTML = val;
    var rootElement = this._htmlParser.childNodes.length !== 1 ? this._htmlParser : this._htmlParser.childNodes[0];
    this._text = '';
    this._htmlText = val;
    this._createTrunk();
    if (rootElement.nodeType === 3) {
      this._convertNode(rootElement, this._tree.children[0].children);
    }
    var initialNodeList = [
        rootElement
      ];
    var attributes;
    var format;
    var key;
    if (initialNodeList.length == 1 && rootElement.localName.toUpperCase() == 'P') {
      attributes = this._extractAttributes(rootElement);
      format = this._tree.format;
      for (key in attributes) {
        format[key] = attributes[key];
      }
      initialNodeList = rootElement.childNodes;
      rootElement = rootElement.childNodes[0];
    }
    if (initialNodeList.length == 1 && rootElement.localName.toUpperCase() == 'FONT') {
      attributes = this._extractAttributes(rootElement);
      format = this._tree.children[0].format;
      for (key in attributes) {
        format[key] = attributes[key];
      }
      initialNodeList = rootElement.childNodes;
    }
    this._convertNodeList(initialNodeList, this._tree.children[0].children);
  },
  _createTrunk: function () {
    var initialFormat = this.defaultTextFormat;
    this._tree = {
      type: 'SPAN',
      format: {
        ALIGN: initialFormat.align
      },
      children: []
    };
    var fontAttributes = {
        FACE: initialFormat.face,
        LETTERSPACING: initialFormat.letterSpacing,
        KERNING: initialFormat.kerning,
        LEADING: initialFormat.leading,
        COLOR: initialFormat.color
      };
    this._tree.children[0] = {
      type: 'FONT',
      format: fontAttributes,
      children: []
    };
  },
  _convertNode: function (input, destinationList) {
    if (!(input.nodeType === 1 || input.nodeType === 3) || input.prefix) {
      return;
    }
    var node;
    if (input.nodeType === 3) {
      var text = input.textContent;
      node = {
        type: 'text',
        text: text,
        format: null,
        children: null
      };
      this._text += text;
      destinationList.push(node);
      return;
    }
    var nodeType = input.localName.toUpperCase();
    if (!TextFieldContent.knownNodeTypes[nodeType] || this.multiline === false && (nodeType === 'P' || nodeType === 'BR')) {
      if (nodeType === 'SBR') {
        destinationList.push({
          type: 'BR',
          text: null,
          format: null,
          children: null
        });
      }
      this._convertNodeList(input.childNodes, destinationList);
      return;
    }
    node = {
      type: nodeType,
      text: null,
      format: this._extractAttributes(input),
      children: []
    };
    this._convertNodeList(input.childNodes, node.children);
    destinationList.push(node);
  },
  _convertNodeList: function (from, to) {
    var childCount = from.length;
    for (var i = 0; i < childCount; i++) {
      this._convertNode(from[i], to);
    }
  },
  _extractAttributes: function (node) {
    var attributesList = node.attributes;
    var attributesMap = {};
    for (var i = 0; i < attributesList.length; i++) {
      var attr = attributesList[i];
      if (attr.prefix) {
        continue;
      }
      attributesMap[attr.localName.toUpperCase()] = attr.value;
    }
    return attributesMap;
  },
  _collectRuns: function (state, node) {
    var formatNode = false;
    var blockNode = false;
    switch (node.type) {
    case 'plain-text':
      var lines = node.lines;
      for (var i = 0; i < lines.length; i++) {
        this._addRunsForText(state, lines[i]);
        if (i < lines.length - 1) {
          this._finishLine(state, true);
        }
      }
      return;
    case 'text':
      this._addRunsForText(state, node.text);
      return;
    case 'BR':
      this._finishLine(state, true);
      return;
    case 'LI':
    case 'P':
      this._finishLine(state, false);
      this._pushFormat(state, node);
      blockNode = true;
      break;
    case 'B':
    case 'I':
    case 'FONT':
    case 'TEXTFORMAT':
      this._pushFormat(state, node);
      formatNode = true;
      break;
    case 'U':
    case 'A':
    case 'IMG':
    case 'SPAN':
    default:
    }
    for (var i = 0; i < node.children.length; i++) {
      var child = node.children[i];
      this._collectRuns(state, child);
    }
    if (formatNode) {
      this._popFormat(state);
    }
    if (blockNode) {
      this._finishLine(state, true);
    }
  },
  _addRunsForText: function (state, text) {
    if (!text) {
      return;
    }
    if (!state.wordWrap) {
      this._addTextRun(state, text, state.ctx.measureText(text).width);
      return;
    }
    while (text.length) {
      var width = state.ctx.measureText(text).width;
      var availableWidth = state.w - state.line.width;
      if (availableWidth <= 0) {
        this._finishLine(state, false);
        availableWidth = state.w - state.line.width;
      }
      if (width <= availableWidth) {
        this._addTextRun(state, text, width);
        break;
      } else {
        var offset = text.length / width * availableWidth | 0;
        while (state.ctx.measureText(text.substr(0, offset)).width < availableWidth && offset < text.length) {
          offset++;
        }
        var wrapOffset = offset;
        while (wrapOffset > -1) {
          if (TextFieldContent.WRAP_OPPORTUNITIES[text[wrapOffset]]) {
            wrapOffset++;
            break;
          }
          wrapOffset--;
        }
        if (wrapOffset === -1) {
          if (state.line.width > 0) {
            this._finishLine(state, false);
            continue;
          }
          while (state.ctx.measureText(text.substr(0, offset)).width > availableWidth) {
            offset--;
          }
          if (offset === 0) {
            offset = 1;
          }
          wrapOffset = offset;
        }
        var runText = text.substr(0, wrapOffset);
        width = state.ctx.measureText(runText).width;
        this._addTextRun(state, runText, width);
        if (state.wordWrap) {
          this._finishLine(state, false);
        }
        text = text.substr(wrapOffset);
      }
    }
  },
  _addTextRun: function (state, text, width) {
    if (text.length === 0) {
      return;
    }
    var line = state.line;
    var format = state.currentFormat;
    var size = format.size;
    var run = {
        type: 't',
        text: text,
        x: line.width
      };
    this._textRuns.push(run);
    state.line.runs.push(run);
    line.width += width | 0;
    if (line.leading === 0 && format.leading > line.leading) {
      line.leading = format.leading;
    }
    if (!line.largestFormat || size > line.largestFormat.size) {
      line.largestFormat = format;
    }
  },
  _finishLine: function (state, forceNewline) {
    var line = state.line;
    if (line.runs.length === 0) {
      if (forceNewline) {
        var format = state.currentFormat;
        state.line.y += format.font._metrics.height * format.size + format.leading | 0;
      }
      return;
    }
    var runs = line.runs;
    var format = line.largestFormat;
    var baselinePos = line.y + format.font._metrics.ascent * format.size;
    for (var i = runs.length; i--;) {
      runs[i].y = baselinePos;
    }
    var align = (state.currentFormat.align || '').toLowerCase();
    if (state.combinedAlign === null) {
      state.combinedAlign = align;
    } else if (state.combinedAlign !== align) {
      state.combinedAlign = 'mixed';
    }
    if (align === 'center' || align === 'right') {
      var offset = Math.max(state.w - line.width, 0);
      if (align === 'center') {
        offset >>= 1;
      }
      for (i = runs.length; i--;) {
        runs[i].x += offset;
      }
    }
    line.height = format.font._metrics.height * format.size + line.leading | 0;
    state.maxLineWidth = Math.max(state.maxLineWidth, line.width);
    this.lines.push(line);
    state.line = new TextFieldContent.TextLine(line.y + line.height);
  },
  _pushFormat: function (state, node) {
    var attributes = node.format;
    var format = Object.create(state.formats[state.formats.length - 1]);
    var fontChanged = false;
    switch (node.type) {
    case 'P':
      if (attributes.ALIGN === format.align) {
        return;
      }
      format.align = attributes.ALIGN;
      break;
    case 'B':
      format.bold = true;
      fontChanged = true;
      break;
    case 'I':
      format.italic = true;
      fontChanged = true;
      break;
    case 'FONT':
      if (attributes.COLOR !== undefined) {
        format.color = attributes.COLOR;
      }
      if (attributes.FACE !== undefined) {
        format.face = attributes.FACE;
        fontChanged = true;
      }
      if (attributes.SIZE !== undefined) {
        format.size = parseFloat(attributes.SIZE);
      }
      if (attributes.LETTERSPACING !== undefined) {
        format.letterspacing = parseFloat(attributes.LETTERSPACING);
      }
      if (attributes.KERNING !== undefined) {
        format.kerning = attributes.KERNING && true;
      }
    case 'TEXTFORMAT':
      if (attributes.LEADING !== undefined) {
        format.leading = parseFloat(attributes.LEADING);
      }
      if (attributes.INDENT !== undefined) {
        state.line.x = attributes.INDENT;
        state.line.width += attributes.INDENT | 0;
      }
      break;
    default:
      warning('Unknown format node encountered: ' + node.type);
      return;
    }
    if (state.textColor !== null) {
      format.color = rgbIntAlphaToStr(state.textColor, 1);
    }
    if (fontChanged) {
      this.resolveFont(format, state.embedFonts);
    }
    format.str = this.makeFormatString(format);
    state.formats.push(format);
    this._textRuns.push({
      type: 'f',
      format: format
    });
    state.currentFormat = format;
    state.ctx.font = format.str;
  },
  _popFormat: function (state) {
    state.formats.pop();
    var format = state.currentFormat = state.formats[state.formats.length - 1];
    this._textRuns.push({
      type: 'f',
      format: format
    });
    state.ctx.font = state.str;
  }
};
var TextFormatDefinition = function () {
    var measureTextField;
    return {
      __class__: 'flash.text.TextFormat',
      initialize: function () {
      },
      fromObject: function (obj) {
        this._font = obj.face || null;
        this._size = typeof obj.size === 'number' ? obj.size : null;
        this._color = typeof obj.color === 'number' ? obj.color : null;
        this._bold = typeof obj.bold === 'boolean' ? obj.bold : null;
        this._italic = typeof obj.italic === 'boolean' ? obj.italic : null;
        this._underline = typeof obj.underline === 'boolean' ? obj.underline : null;
        this._url = obj.url || null;
        this._target = obj.target || null;
        this._align = obj.align || null;
        this._leftMargin = typeof obj.leftMargin === 'number' ? obj.leftMargin : null;
        this._rightMargin = typeof obj.rightMargin === 'number' ? obj.rightMargin : null;
        this._indent = typeof obj.indent === 'number' ? obj.indent : null;
        this._leading = typeof obj.leading === 'number' ? obj.leading : null;
        return this;
      },
      toObject: function () {
        return {
          face: this._font || 'serif',
          size: this._size || 12,
          color: this._color || 0,
          bold: this._bold || false,
          italic: this._italic || false,
          underline: this._underline || false,
          url: this._url,
          target: this._target,
          align: this._align || 'left',
          leftMargin: this._leftMargin || 0,
          rightMargin: this._rightMargin || 0,
          indent: this._indent || 0,
          leading: this._leading || 0
        };
      },
      as2GetTextExtent: function (text, width) {
        if (!measureTextField) {
          measureTextField = new flash.text.TextField();
          measureTextField._multiline = true;
        }
        if (!isNaN(width) && width > 0) {
          measureTextField.width = width + 4;
          measureTextField._wordWrap = true;
        } else {
          measureTextField._wordWrap = false;
        }
        measureTextField.defaultTextFormat = this;
        measureTextField.text = text;
        measureTextField.ensureDimensions();
        var result = {};
        var textWidth = measureTextField._textWidth;
        var textHeight = measureTextField._textHeight;
        result.asSetPublicProperty('width', textWidth);
        result.asSetPublicProperty('height', textHeight);
        result.asSetPublicProperty('textFieldWidth', textWidth + 4);
        result.asSetPublicProperty('textFieldHeight', textHeight + 4);
        var metrics = measureTextField.getLineMetrics(0);
        result.asSetPublicProperty('ascent', metrics.asGetPublicProperty('ascent'));
        result.asSetPublicProperty('descent', metrics.asGetPublicProperty('descent'));
        return result;
      },
      __glue__: {
        native: {
          static: {},
          instance: {
            align: {
              get: function align() {
                return this._align;
              },
              set: function align(value) {
                this._align = value;
              }
            },
            blockIndent: {
              get: function blockIndent() {
                return this._blockIndent;
              },
              set: function blockIndent(value) {
                this._blockIndent = value;
              }
            },
            bold: {
              get: function bold() {
                return this._bold;
              },
              set: function bold(value) {
                this._bold = value;
              }
            },
            bullet: {
              get: function bullet() {
                return this._bullet;
              },
              set: function bullet(value) {
                this._bullet = value;
              }
            },
            color: {
              get: function color() {
                return this._color;
              },
              set: function color(value) {
                this._color = value;
              }
            },
            display: {
              get: function display() {
                return this._display;
              },
              set: function display(value) {
                this._display = value;
              }
            },
            font: {
              get: function font() {
                return this._font;
              },
              set: function font(value) {
                this._font = value;
              }
            },
            indent: {
              get: function indent() {
                return this._indent;
              },
              set: function indent(value) {
                this._indent = value;
              }
            },
            italic: {
              get: function italic() {
                return this._italic;
              },
              set: function italic(value) {
                this._italic = value;
              }
            },
            kerning: {
              get: function kerning() {
                return this._kerning;
              },
              set: function kerning(value) {
                this._kerning = value;
              }
            },
            leading: {
              get: function leading() {
                return this._leading;
              },
              set: function leading(value) {
                this._leading = value;
              }
            },
            leftMargin: {
              get: function leftMargin() {
                return this._leftMargin;
              },
              set: function leftMargin(value) {
                this._leftMargin = value;
              }
            },
            letterSpacing: {
              get: function letterSpacing() {
                return this._letterSpacing;
              },
              set: function letterSpacing(value) {
                this._letterSpacing = value;
              }
            },
            rightMargin: {
              get: function rightMargin() {
                return this._rightMargin;
              },
              set: function rightMargin(value) {
                this._rightMargin = value;
              }
            },
            size: {
              get: function size() {
                return this._size;
              },
              set: function size(value) {
                this._size = value;
              }
            },
            tabStops: {
              get: function tabStops() {
                return this._tabStops;
              },
              set: function tabStops(value) {
                this._tabStops = value;
              }
            },
            target: {
              get: function target() {
                return this._target;
              },
              set: function target(value) {
                this._target = value;
              }
            },
            underline: {
              get: function underline() {
                return this._underline;
              },
              set: function underline(value) {
                this._underline = value;
              }
            },
            url: {
              get: function url() {
                return this._url;
              },
              set: function url(value) {
                this._url = value;
              }
            }
          }
        }
      }
    };
  }.call(this);
var ContentElementDefinition = function () {
    return {
      __class__: 'flash.text.engine.ContentElement',
      initialize: function () {
      },
      __glue__: {
        native: {
          static: {},
          instance: {
            textBlock: {
              get: function textBlock() {
                notImplemented('ContentElement.textBlock');
                return this._textBlock;
              }
            },
            textBlockBeginIndex: {
              get: function textBlockBeginIndex() {
                notImplemented('ContentElement.textBlockBeginIndex');
                return this._textBlockBeginIndex;
              }
            },
            elementFormat: {
              get: function elementFormat() {
                return this._elementFormat;
              },
              set: function elementFormat(value) {
                somewhatImplemented('ContentElement.elementFormat');
                this._elementFormat = value;
              }
            },
            eventMirror: {
              get: function eventMirror() {
                return this._eventMirror;
              },
              set: function eventMirror(value) {
                somewhatImplemented('ContentElement.eventMirror');
                this._eventMirror = value;
              }
            },
            groupElement: {
              get: function groupElement() {
                notImplemented('ContentElement.groupElement');
                return this._groupElement;
              }
            },
            rawText: {
              get: function rawText() {
                notImplemented('ContentElement.rawText');
                return this._rawText;
              }
            },
            text: {
              get: function text() {
                notImplemented('ContentElement.text');
                return this._text;
              }
            },
            textRotation: {
              get: function textRotation() {
                return this._textRotation;
              },
              set: function textRotation(value) {
                somewhatImplemented('ContentElement.textRotation');
                this._textRotation = value;
              }
            }
          }
        }
      }
    };
  }.call(this);
var ElementFormatDefinition = function () {
    return {
      __class__: 'flash.text.engine.ElementFormat',
      initialize: function () {
      },
      __glue__: {
        native: {
          static: {},
          instance: {
            getFontMetrics: function getFontMetrics() {
              notImplemented('ElementFormat.getFontMetrics');
            },
            alignmentBaseline: {
              get: function alignmentBaseline() {
                return this._alignmentBaseline;
              },
              set: function alignmentBaseline(alignmentBaseline) {
                somewhatImplemented('ElementFormat.alignmentBaseline');
                this._alignmentBaseline = alignmentBaseline;
              }
            },
            alpha: {
              get: function alpha() {
                return this._alpha;
              },
              set: function alpha(value) {
                somewhatImplemented('ElementFormat.alpha');
                this._alpha = value;
              }
            },
            baselineShift: {
              get: function baselineShift() {
                return this._baselineShift;
              },
              set: function baselineShift(value) {
                somewhatImplemented('ElementFormat.baselineShift');
                this._baselineShift = value;
              }
            },
            breakOpportunity: {
              get: function breakOpportunity() {
                return this._breakOpportunity;
              },
              set: function breakOpportunity(opportunityType) {
                somewhatImplemented('ElementFormat.breakOpportunity');
                this._breakOpportunity = opportunityType;
              }
            },
            color: {
              get: function color() {
                return this._color;
              },
              set: function color(value) {
                somewhatImplemented('ElementFormat.color');
                this._color = value;
              }
            },
            dominantBaseline: {
              get: function dominantBaseline() {
                return this._dominantBaseline;
              },
              set: function dominantBaseline(dominantBaseline) {
                somewhatImplemented('ElementFormat.dominantBaseline');
                this._dominantBaseline = dominantBaseline;
              }
            },
            fontDescription: {
              get: function fontDescription() {
                return this._fontDescription;
              },
              set: function fontDescription(value) {
                somewhatImplemented('ElementFormat.fontDescription');
                this._fontDescription = value;
              }
            },
            digitCase: {
              get: function digitCase() {
                return this._digitCase;
              },
              set: function digitCase(digitCaseType) {
                somewhatImplemented('ElementFormat.digitCase');
                this._digitCase = digitCaseType;
              }
            },
            digitWidth: {
              get: function digitWidth() {
                return this._digitWidth;
              },
              set: function digitWidth(digitWidthType) {
                somewhatImplemented('ElementFormat.digitWidth');
                this._digitWidth = digitWidthType;
              }
            },
            ligatureLevel: {
              get: function ligatureLevel() {
                return this._ligatureLevel;
              },
              set: function ligatureLevel(ligatureLevelType) {
                somewhatImplemented('ElementFormat.ligatureLevel');
                this._ligatureLevel = ligatureLevelType;
              }
            },
            fontSize: {
              get: function fontSize() {
                return this._fontSize;
              },
              set: function fontSize(value) {
                somewhatImplemented('ElementFormat.fontSize');
                this._fontSize = value;
              }
            },
            kerning: {
              get: function kerning() {
                return this._kerning;
              },
              set: function kerning(value) {
                somewhatImplemented('ElementFormat.kerning');
                this._kerning = value;
              }
            },
            locale: {
              get: function locale() {
                return this._locale;
              },
              set: function locale(value) {
                somewhatImplemented('ElementFormat.locale');
                this._locale = value;
              }
            },
            textRotation: {
              get: function textRotation() {
                return this._textRotation;
              },
              set: function textRotation(value) {
                somewhatImplemented('ElementFormat.textRotation');
                this._textRotation = value;
              }
            },
            trackingRight: {
              get: function trackingRight() {
                return this._trackingRight;
              },
              set: function trackingRight(value) {
                somewhatImplemented('ElementFormat.trackingRight');
                this._trackingRight = value;
              }
            },
            trackingLeft: {
              get: function trackingLeft() {
                return this._trackingLeft;
              },
              set: function trackingLeft(value) {
                somewhatImplemented('ElementFormat.trackingLeft');
                this._trackingLeft = value;
              }
            },
            typographicCase: {
              get: function typographicCase() {
                return this._typographicCase;
              },
              set: function typographicCase(typographicCaseType) {
                somewhatImplemented('ElementFormat.typographicCase');
                this._typographicCase = typographicCaseType;
              }
            },
            locked: {
              get: function locked() {
                notImplemented('ElementFormat.locked');
                return this._locked;
              },
              set: function locked(value) {
                notImplemented('ElementFormat.locked');
                this._locked = value;
              }
            }
          }
        }
      }
    };
  }.call(this);
var FontDescriptionDefinition = function () {
    return {
      __class__: 'flash.text.engine.FontDescription',
      initialize: function () {
      },
      __glue__: {
        native: {
          static: {
            isFontCompatible: function isFontCompatible(fontName, fontWeight, fontPosture) {
              notImplemented('FontDescription.isFontCompatible');
            },
            isDeviceFontCompatible: function isDeviceFontCompatible(fontName, fontWeight, fontPosture) {
              notImplemented('FontDescription.isDeviceFontCompatible');
            }
          },
          instance: {
            renderingMode: {
              get: function renderingMode() {
                return this._renderingMode;
              },
              set: function renderingMode(value) {
                somewhatImplemented('FontDescription.renderingMode');
                this._renderingMode = value;
              }
            },
            fontLookup: {
              get: function fontLookup() {
                return this._fontLookup;
              },
              set: function fontLookup(value) {
                somewhatImplemented('FontDescription.fontLookup');
                this._fontLookup = value;
              }
            },
            fontName: {
              get: function fontName() {
                return this._fontName;
              },
              set: function fontName(value) {
                somewhatImplemented('FontDescription.fontName');
                this._fontName = value;
              }
            },
            fontPosture: {
              get: function fontPosture() {
                return this._fontPosture;
              },
              set: function fontPosture(value) {
                somewhatImplemented('FontDescription.fontPosture');
                this._fontPosture = value;
              }
            },
            fontWeight: {
              get: function fontWeight() {
                return this._fontWeight;
              },
              set: function fontWeight(value) {
                somewhatImplemented('FontDescription.fontWeight');
                this._fontWeight = value;
              }
            },
            cffHinting: {
              get: function cffHinting() {
                return this._cffHinting;
              },
              set: function cffHinting(value) {
                somewhatImplemented('FontDescription.cffHinting');
                this._cffHinting = value;
              }
            },
            locked: {
              get: function locked() {
                notImplemented('FontDescription.locked');
                return this._locked;
              },
              set: function locked(value) {
                notImplemented('FontDescription.locked');
                this._locked = value;
              }
            }
          }
        },
        script: {
          static: {},
          instance: {}
        }
      }
    };
  }.call(this);
var GroupElementDefinition = function () {
    return {
      __class__: 'flash.text.engine.GroupElement',
      initialize: function () {
      },
      __glue__: {
        native: {
          static: {},
          instance: {
            getElementAt: function getElementAt(index) {
              notImplemented('GroupElement.getElementAt');
            },
            setElements: function setElements(value) {
              somewhatImplemented('GroupElement.setElements');
              this._elements = value;
            },
            groupElements: function groupElements(beginIndex, endIndex) {
              notImplemented('GroupElement.groupElements');
            },
            ungroupElements: function ungroupElements(groupIndex) {
              notImplemented('GroupElement.ungroupElements');
            },
            mergeTextElements: function mergeTextElements(beginIndex, endIndex) {
              notImplemented('GroupElement.mergeTextElements');
            },
            splitTextElement: function splitTextElement(elementIndex, splitIndex) {
              notImplemented('GroupElement.splitTextElement');
            },
            replaceElements: function replaceElements(beginIndex, endIndex, newElements) {
              notImplemented('GroupElement.replaceElements');
            },
            getElementAtCharIndex: function getElementAtCharIndex(charIndex) {
              notImplemented('GroupElement.getElementAtCharIndex');
            },
            elementCount: {
              get: function elementCount() {
                notImplemented('GroupElement.elementCount');
                return this._elementCount;
              }
            }
          }
        }
      }
    };
  }.call(this);
var SpaceJustifierDefinition = function () {
    return {
      __class__: 'flash.text.engine.SpaceJustifier',
      initialize: function () {
        this._letterSpacing = false;
        this._optimumSpacing = 1;
        this._minimumSpacing = 0.5;
        this._maximumSpacing = 1.5;
      },
      __glue__: {
        native: {
          static: {},
          instance: {
            cloneSpacing: function cloneSpacing(justifier) {
              somewhatImplemented('SpaceJustifier.cloneSpacing');
              justifier._optimumSpacing = this._optimumSpacing;
              justifier._minimumSpacing = this._minimumSpacing;
              justifier._maximumSpacing = this._maximumSpacing;
            },
            letterSpacing: {
              get: function letterSpacing() {
                return this._letterSpacing;
              },
              set: function letterSpacing(value) {
                somewhatImplemented('SpaceJustifier.letterSpacing');
                this._letterSpacing = value;
              }
            },
            minimumSpacing: {
              get: function minimumSpacing() {
                return this._minimumSpacing;
              },
              set: function minimumSpacing(value) {
                somewhatImplemented('SpaceJustifier.minimumSpacing');
                this._minimumSpacing = value;
              }
            },
            optimumSpacing: {
              get: function optimumSpacing() {
                return this._optimumSpacing;
              },
              set: function optimumSpacing(value) {
                somewhatImplemented('SpaceJustifier.optimumSpacing');
                this._optimumSpacing = value;
              }
            },
            maximumSpacing: {
              get: function maximumSpacing() {
                return this._maximumSpacing;
              },
              set: function maximumSpacing(value) {
                somewhatImplemented('SpaceJustifier.maximumSpacing');
                this._maximumSpacing = value;
              }
            }
          }
        }
      }
    };
  }.call(this);
var TextBlockDefinition = function () {
    return {
      __class__: 'flash.text.engine.TextBlock',
      initialize: function () {
        this._firstLine = null;
        this._lastLine = null;
      },
      __glue__: {
        native: {
          static: {},
          instance: {
            getTextJustifier: function getTextJustifier() {
              return this._textJustifier;
            },
            setTextJustifier: function setTextJustifier(value) {
              somewhatImplemented('TextBlock.setTextJustifier');
              this._textJustifier = value;
            },
            getTabStops: function getTabStops() {
              return this._tabStops;
            },
            setTabStops: function setTabStops(value) {
              somewhatImplemented('TextBlock.setTabStops');
              this._tabStops = value;
            },
            findNextAtomBoundary: function findNextAtomBoundary(afterCharIndex) {
              notImplemented('TextBlock.findNextAtomBoundary');
            },
            findPreviousAtomBoundary: function findPreviousAtomBoundary(beforeCharIndex) {
              notImplemented('TextBlock.findPreviousAtomBoundary');
            },
            findNextWordBoundary: function findNextWordBoundary(afterCharIndex) {
              notImplemented('TextBlock.findNextWordBoundary');
            },
            findPreviousWordBoundary: function findPreviousWordBoundary(beforeCharIndex) {
              notImplemented('TextBlock.findPreviousWordBoundary');
            },
            getTextLineAtCharIndex: function getTextLineAtCharIndex(charIndex) {
              notImplemented('TextBlock.getTextLineAtCharIndex');
            },
            DoCreateTextLine: function DoCreateTextLine(previousLine, width, lineOffset, fitSomething, reuseLine) {
              somewhatImplemented('TextBlock.DoCreateTextLine');
              if (previousLine) {
                return null;
              }
              var textLine = new flash.text.engine.TextLine();
              textLine._textBlock = this;
              textLine._specifiedWidth = width;
              textLine._rawTextLength = 0;
              textLine._textWidth = 0;
              textLine._textHeight = 0;
              textLine._ascent = 0;
              textLine._descent = 0;
              textLine._unjustifiedTextWidth = 0;
              textLine._validity = 'valid';
              textLine._previousLine = null;
              textLine._nextLine = null;
              this._firstLine = textLine;
              this._lastLine = textLine;
              return textLine;
            },
            releaseLineCreationData: function releaseLineCreationData() {
              notImplemented('TextBlock.releaseLineCreationData');
            },
            releaseLines: function releaseLines(firstLine, lastLine) {
              notImplemented('TextBlock.releaseLines');
            },
            dump: function dump() {
              notImplemented('TextBlock.dump');
            },
            applyNonLinearFontScaling: {
              get: function applyNonLinearFontScaling() {
                return this._applyNonLinearFontScaling;
              },
              set: function applyNonLinearFontScaling(value) {
                somewhatImplemented('TextBlock.applyNonLinearFontScaling');
                this._applyNonLinearFontScaling = value;
              }
            },
            baselineFontDescription: {
              get: function baselineFontDescription() {
                return this._baselineFontDescription;
              },
              set: function baselineFontDescription(value) {
                somewhatImplemented('TextBlock.baselineFontDescription');
                this._baselineFontDescription = value;
              }
            },
            baselineFontSize: {
              get: function baselineFontSize() {
                return this._baselineFontSize;
              },
              set: function baselineFontSize(value) {
                somewhatImplemented('TextBlock.baselineFontSize');
                this._baselineFontSize = value;
              }
            },
            baselineZero: {
              get: function baselineZero() {
                return this._baselineZero;
              },
              set: function baselineZero(value) {
                somewhatImplemented('TextBlock.baselineZero');
                this._baselineZero = value;
              }
            },
            content: {
              get: function content() {
                return this._content;
              },
              set: function content(value) {
                somewhatImplemented('TextBlock.content');
                this._content = value;
              }
            },
            bidiLevel: {
              get: function bidiLevel() {
                return this._bidiLevel;
              },
              set: function bidiLevel(value) {
                somewhatImplemented('TextBlock.bidiLevel');
                this._bidiLevel = value;
              }
            },
            firstInvalidLine: {
              get: function firstInvalidLine() {
                notImplemented('TextBlock.firstInvalidLine');
                return this._firstInvalidLine;
              }
            },
            firstLine: {
              get: function firstLine() {
                somewhatImplemented('TextBlock.firstLine');
                return this._firstLine;
              }
            },
            lastLine: {
              get: function lastLine() {
                somewhatImplemented('TextBlock.lastLine');
                return this._lastLine;
              }
            },
            textLineCreationResult: {
              get: function textLineCreationResult() {
                notImplemented('TextBlock.textLineCreationResult');
                return this._textLineCreationResult;
              }
            },
            lineRotation: {
              get: function lineRotation() {
                return this._lineRotation;
              },
              set: function lineRotation(value) {
                somewhatImplemented('TextBlock.lineRotation');
                this._lineRotation = value;
              }
            }
          }
        }
      }
    };
  }.call(this);
var TextElementDefinition = function () {
    return {
      __class__: 'flash.text.engine.TextElement',
      initialize: function () {
      },
      __glue__: {
        native: {
          static: {},
          instance: {
            replaceText: function replaceText(beginIndex, endIndex, newText) {
              somewhatImplemented('TextElement.replaceText');
              var text = this._text || '';
              this._text = text.slice(0, beginIndex) + newText + text.slice(endIndex);
            },
            text: {
              set: function text(value) {
                somewhatImplemented('TextElement.text');
                this._text = value;
              }
            }
          }
        }
      }
    };
  }.call(this);
var TextJustifierDefinition = function () {
    return {
      __class__: 'flash.text.engine.TextJustifier',
      initialize: function () {
        this._locale = null;
        this._lineJustification = null;
      },
      __glue__: {
        native: {
          static: {},
          instance: {
            setLocale: function setLocale(value) {
              somewhatImplemented('TextJustifier.setLocale');
              this._locale = value;
            },
            locale: {
              get: function locale() {
                return this._locale;
              }
            },
            lineJustification: {
              get: function lineJustification() {
                return this._lineJustification;
              },
              set: function lineJustification(value) {
                somewhatImplemented('TextJustifier.lineJustification');
                this._lineJustification = value;
              }
            }
          }
        }
      }
    };
  }.call(this);
var TextLineDefinition = function () {
    return {
      __class__: 'flash.text.engine.TextLine',
      initialize: function () {
      },
      __glue__: {
        native: {
          static: {},
          instance: {
            getAtomIndexAtPoint: function getAtomIndexAtPoint(stageX, stageY) {
              notImplemented('TextLine.getAtomIndexAtPoint');
            },
            getAtomIndexAtCharIndex: function getAtomIndexAtCharIndex(charIndex) {
              notImplemented('TextLine.getAtomIndexAtCharIndex');
            },
            getAtomBounds: function getAtomBounds(atomIndex) {
              notImplemented('TextLine.getAtomBounds');
            },
            getAtomBidiLevel: function getAtomBidiLevel(atomIndex) {
              notImplemented('TextLine.getAtomBidiLevel');
            },
            getAtomTextRotation: function getAtomTextRotation(atomIndex) {
              notImplemented('TextLine.getAtomTextRotation');
            },
            getAtomTextBlockBeginIndex: function getAtomTextBlockBeginIndex(atomIndex) {
              notImplemented('TextLine.getAtomTextBlockBeginIndex');
            },
            getAtomTextBlockEndIndex: function getAtomTextBlockEndIndex(atomIndex) {
              notImplemented('TextLine.getAtomTextBlockEndIndex');
            },
            getAtomCenter: function getAtomCenter(atomIndex) {
              notImplemented('TextLine.getAtomCenter');
            },
            getAtomWordBoundaryOnLeft: function getAtomWordBoundaryOnLeft(atomIndex) {
              notImplemented('TextLine.getAtomWordBoundaryOnLeft');
            },
            getAtomGraphic: function getAtomGraphic(atomIndex) {
              notImplemented('TextLine.getAtomGraphic');
            },
            getBaselinePosition: function getBaselinePosition(baseline) {
              notImplemented('TextLine.getBaselinePosition');
            },
            dump: function dump() {
              notImplemented('TextLine.dump');
            },
            textBlock: {
              get: function textBlock() {
                notImplemented('TextLine.textBlock');
                return this._textBlock;
              }
            },
            hasGraphicElement: {
              get: function hasGraphicElement() {
                notImplemented('TextLine.hasGraphicElement');
                return this._hasGraphicElement;
              }
            },
            hasTabs: {
              get: function hasTabs() {
                notImplemented('TextLine.hasTabs');
                return this._hasTabs;
              }
            },
            nextLine: {
              get: function nextLine() {
                somewhatImplemented('TextLine.nextLine');
                return this._nextLine;
              }
            },
            previousLine: {
              get: function previousLine() {
                somewhatImplemented('TextLine.previousLine');
                return this._previousLine;
              }
            },
            ascent: {
              get: function ascent() {
                somewhatImplemented('TextLine.ascent');
                return this._ascent;
              }
            },
            descent: {
              get: function descent() {
                somewhatImplemented('TextLine.descent');
                return this._descent;
              }
            },
            textHeight: {
              get: function textHeight() {
                somewhatImplemented('TextLine.textHeight');
                return this._textHeight;
              }
            },
            textWidth: {
              get: function textWidth() {
                somewhatImplemented('TextLine.textWidth');
                return this._textWidth;
              }
            },
            totalAscent: {
              get: function totalAscent() {
                notImplemented('TextLine.totalAscent');
                return this._totalAscent;
              }
            },
            totalDescent: {
              get: function totalDescent() {
                notImplemented('TextLine.totalDescent');
                return this._totalDescent;
              }
            },
            totalHeight: {
              get: function totalHeight() {
                notImplemented('TextLine.totalHeight');
                return this._totalHeight;
              }
            },
            textBlockBeginIndex: {
              get: function textBlockBeginIndex() {
                notImplemented('TextLine.textBlockBeginIndex');
                return this._textBlockBeginIndex;
              }
            },
            rawTextLength: {
              get: function rawTextLength() {
                somewhatImplemented('TextLine.rawTextLength');
                return this._rawTextLength;
              }
            },
            specifiedWidth: {
              get: function specifiedWidth() {
                somewhatImplemented('TextLine.specifiedWidth');
                return this._specifiedWidth;
              }
            },
            unjustifiedTextWidth: {
              get: function unjustifiedTextWidth() {
                somewhatImplemented('TextLine.unjustifiedTextWidth');
                return this._unjustifiedTextWidth;
              }
            },
            validity: {
              get: function validity() {
                return this._validity;
              },
              set: function validity(value) {
                somewhatImplemented('TextLine.validity');
                this._validity = value;
              }
            },
            atomCount: {
              get: function atomCount() {
                notImplemented('TextLine.atomCount');
                return this._atomCount;
              }
            },
            mirrorRegions: {
              get: function mirrorRegions() {
                notImplemented('TextLine.mirrorRegions');
                return this._mirrorRegions;
              }
            }
          }
        }
      }
    };
  }.call(this);
{
  var ContextMenuDefinition = function () {
      return {
        __class__: 'flash.ui.ContextMenu',
        initialize: function () {
        },
        __glue__: {
          native: {
            static: {
              _checkSupported: function _checkSupported() {
                notImplemented('ContextMenu._checkSupported');
              }
            },
            instance: {
              cloneLinkAndClipboardProperties: function cloneLinkAndClipboardProperties(c) {
                notImplemented('ContextMenu.cloneLinkAndClipboardProperties');
              },
              builtInItems: {
                get: function builtInItems() {
                  somewhatImplemented('ContextMenu.builtInItems');
                  return this._builtInItems;
                },
                set: function builtInItems(value) {
                  somewhatImplemented('ContextMenu.builtInItems');
                  this._builtInItems = value;
                }
              },
              customItems: {
                get: function customItems() {
                  somewhatImplemented('ContextMenu.customItems');
                  return this._customItems;
                },
                set: function customItems(value) {
                  somewhatImplemented('ContextMenu.customItems');
                  this._customItems = value;
                }
              },
              link: {
                get: function link() {
                  notImplemented('ContextMenu.link');
                  return this._link;
                },
                set: function link(value) {
                  notImplemented('ContextMenu.link');
                  this._link = value;
                }
              },
              clipboardMenu: {
                get: function clipboardMenu() {
                  notImplemented('ContextMenu.clipboardMenu');
                  return this._clipboardMenu;
                },
                set: function clipboardMenu(value) {
                  notImplemented('ContextMenu.clipboardMenu');
                  this._clipboardMenu = value;
                }
              },
              clipboardItems: {
                get: function clipboardItems() {
                  notImplemented('ContextMenu.clipboardItems');
                  return this._clipboardItems;
                },
                set: function clipboardItems(value) {
                  notImplemented('ContextMenu.clipboardItems');
                  this._clipboardItems = value;
                }
              }
            }
          }
        }
      };
    }.call(this);
}
var ContextMenuItemDefinition = function () {
    return {
      __class__: 'flash.ui.ContextMenuItem',
      initialize: function () {
      },
      __glue__: {
        native: {
          static: {},
          instance: {
            caption: {
              get: function caption() {
                somewhatImplemented('ContextMenuItem.caption');
                return this._caption;
              },
              set: function caption(value) {
                somewhatImplemented('ContextMenuItem.caption');
                this._caption = value;
              }
            },
            separatorBefore: {
              get: function separatorBefore() {
                somewhatImplemented('ContextMenuItem.separatorBefore');
                return this._separatorBefore;
              },
              set: function separatorBefore(value) {
                somewhatImplemented('ContextMenuItem.separatorBefore');
                this._separatorBefore = value;
              }
            },
            visible: {
              get: function visible() {
                somewhatImplemented('ContextMenuItem.visible');
                return this._visible;
              },
              set: function visible(value) {
                somewhatImplemented('ContextMenuItem.visible');
                this._visible = value;
              }
            }
          }
        }
      }
    };
  }.call(this);
var ShumwayKeyboardListener = {
    _lastKeyCode: 0,
    _captureKeyPress: false,
    _charCodeMap: [],
    focus: null,
    handleEvent: function (domEvt) {
      var keyCode = domEvt.keyCode;
      if (domEvt.type === 'keydown') {
        this._lastKeyCode = keyCode;
        this._captureKeyPress = keyCode === 8 || keyCode === 9 || keyCode === 13 || keyCode === 32 || keyCode >= 48 && keyCode <= 90 || keyCode > 145;
        if (this._captureKeyPress) {
          return;
        }
        this._charCodeMap[keyCode] = 0;
      } else if (domEvt.type === 'keypress') {
        if (this._captureKeyPress) {
          keyCode = this._lastKeyCode;
          this._charCodeMap[keyCode] = domEvt.charCode;
        } else {
          return;
        }
      }
      if (this.focus) {
        this.focus._dispatchEvent(new flash.events.KeyboardEvent(domEvt.type === 'keyup' ? 'keyUp' : 'keyDown', true, false, domEvt.type === 'keyup' ? this._charCodeMap[keyCode] : domEvt.charCode, domEvt.type === 'keyup' ? domEvt.keyCode : this._lastKeyCode, domEvt.keyLocation, domEvt.ctrlKey, domEvt.altKey, domEvt.shiftKey));
      }
    }
  };
window.addEventListener('keydown', ShumwayKeyboardListener);
window.addEventListener('keypress', ShumwayKeyboardListener);
window.addEventListener('keyup', ShumwayKeyboardListener);
var KeyboardDefinition = function () {
    var def = {
        get capsLock() {
          return false;
        },
        get hasVirtualKeyboard() {
          return false;
        },
        get numLock() {
          return false;
        },
        get physicalKeyboardType() {
          return 'alphanumeric';
        },
        get isAccessible() {
          return true;
        }
      };
    var desc = Object.getOwnPropertyDescriptor;
    def.__glue__ = {
      script: {
        static: scriptProperties('public', [
          'A',
          'ALTERNATE',
          'AUDIO',
          'B',
          'BACK',
          'BACKQUOTE',
          'BACKSLASH',
          'BACKSPACE',
          'BLUE',
          'C',
          'CAPS_LOCK',
          'CHANNEL_DOWN',
          'CHANNEL_UP',
          'COMMA',
          'COMMAND',
          'CONTROL',
          'D',
          'DELETE',
          'DOWN',
          'DVR',
          'E',
          'END',
          'ENTER',
          'EQUAL',
          'ESCAPE',
          'EXIT',
          'F',
          'F1',
          'F10',
          'F11',
          'F12',
          'F13',
          'F14',
          'F15',
          'F2',
          'F3',
          'F4',
          'F5',
          'F6',
          'F7',
          'F8',
          'F9',
          'FAST_FORWARD',
          'G',
          'GREEN',
          'GUIDE',
          'H',
          'HELP',
          'HOME',
          'I',
          'INFO',
          'INPUT',
          'INSERT',
          'J',
          'K',
          'KEYNAME_BEGIN',
          'KEYNAME_BREAK',
          'KEYNAME_CLEARDISPLAY',
          'KEYNAME_CLEARLINE',
          'KEYNAME_DELETE',
          'KEYNAME_DELETECHAR',
          'KEYNAME_DELETELINE',
          'KEYNAME_DOWNARROW',
          'KEYNAME_END',
          'KEYNAME_EXECUTE',
          'KEYNAME_F1',
          'KEYNAME_F10',
          'KEYNAME_F11',
          'KEYNAME_F12',
          'KEYNAME_F13',
          'KEYNAME_F14',
          'KEYNAME_F15',
          'KEYNAME_F16',
          'KEYNAME_F17',
          'KEYNAME_F18',
          'KEYNAME_F19',
          'KEYNAME_F2',
          'KEYNAME_F20',
          'KEYNAME_F21',
          'KEYNAME_F22',
          'KEYNAME_F23',
          'KEYNAME_F24',
          'KEYNAME_F25',
          'KEYNAME_F26',
          'KEYNAME_F27',
          'KEYNAME_F28',
          'KEYNAME_F29',
          'KEYNAME_F3',
          'KEYNAME_F30',
          'KEYNAME_F31',
          'KEYNAME_F32',
          'KEYNAME_F33',
          'KEYNAME_F34',
          'KEYNAME_F35',
          'KEYNAME_F4',
          'KEYNAME_F5',
          'KEYNAME_F6',
          'KEYNAME_F7',
          'KEYNAME_F8',
          'KEYNAME_F9',
          'KEYNAME_FIND',
          'KEYNAME_HELP',
          'KEYNAME_HOME',
          'KEYNAME_INSERT',
          'KEYNAME_INSERTCHAR',
          'KEYNAME_INSERTLINE',
          'KEYNAME_LEFTARROW',
          'KEYNAME_MENU',
          'KEYNAME_MODESWITCH',
          'KEYNAME_NEXT',
          'KEYNAME_PAGEDOWN',
          'KEYNAME_PAGEUP',
          'KEYNAME_PAUSE',
          'KEYNAME_PREV',
          'KEYNAME_PRINT',
          'KEYNAME_PRINTSCREEN',
          'KEYNAME_REDO',
          'KEYNAME_RESET',
          'KEYNAME_RIGHTARROW',
          'KEYNAME_SCROLLLOCK',
          'KEYNAME_SELECT',
          'KEYNAME_STOP',
          'KEYNAME_SYSREQ',
          'KEYNAME_SYSTEM',
          'KEYNAME_UNDO',
          'KEYNAME_UPARROW',
          'KEYNAME_USER',
          'L',
          'LAST',
          'LEFT',
          'LEFTBRACKET',
          'LIVE',
          'M',
          'MASTER_SHELL',
          'MENU',
          'MINUS',
          'N',
          'NEXT',
          'NUMBER_0',
          'NUMBER_1',
          'NUMBER_2',
          'NUMBER_3',
          'NUMBER_4',
          'NUMBER_5',
          'NUMBER_6',
          'NUMBER_7',
          'NUMBER_8',
          'NUMBER_9',
          'NUMPAD',
          'NUMPAD_0',
          'NUMPAD_1',
          'NUMPAD_2',
          'NUMPAD_3',
          'NUMPAD_4',
          'NUMPAD_5',
          'NUMPAD_6',
          'NUMPAD_7',
          'NUMPAD_8',
          'NUMPAD_9',
          'NUMPAD_ADD',
          'NUMPAD_DECIMAL',
          'NUMPAD_DIVIDE',
          'NUMPAD_ENTER',
          'NUMPAD_MULTIPLY',
          'NUMPAD_SUBTRACT',
          'O',
          'P',
          'PAGE_DOWN',
          'PAGE_UP',
          'PAUSE',
          'PERIOD',
          'PLAY',
          'PREVIOUS',
          'Q',
          'QUOTE',
          'R',
          'RECORD',
          'RED',
          'REWIND',
          'RIGHT',
          'RIGHTBRACKET',
          'S',
          'SEARCH',
          'SEMICOLON',
          'SETUP',
          'SHIFT',
          'SKIP_BACKWARD',
          'SKIP_FORWARD',
          'SLASH',
          'SPACE',
          'STOP',
          'STRING_BEGIN',
          'STRING_BREAK',
          'STRING_CLEARDISPLAY',
          'STRING_CLEARLINE',
          'STRING_DELETE',
          'STRING_DELETECHAR',
          'STRING_DELETELINE',
          'STRING_DOWNARROW',
          'STRING_END',
          'STRING_EXECUTE',
          'STRING_F1',
          'STRING_F10',
          'STRING_F11',
          'STRING_F12',
          'STRING_F13',
          'STRING_F14',
          'STRING_F15',
          'STRING_F16',
          'STRING_F17',
          'STRING_F18',
          'STRING_F19',
          'STRING_F2',
          'STRING_F20',
          'STRING_F21',
          'STRING_F22',
          'STRING_F23',
          'STRING_F24',
          'STRING_F25',
          'STRING_F26',
          'STRING_F27',
          'STRING_F28',
          'STRING_F29',
          'STRING_F3',
          'STRING_F30',
          'STRING_F31',
          'STRING_F32',
          'STRING_F33',
          'STRING_F34',
          'STRING_F35',
          'STRING_F4',
          'STRING_F5',
          'STRING_F6',
          'STRING_F7',
          'STRING_F8',
          'STRING_F9',
          'STRING_FIND',
          'STRING_HELP',
          'STRING_HOME',
          'STRING_INSERT',
          'STRING_INSERTCHAR',
          'STRING_INSERTLINE',
          'STRING_LEFTARROW',
          'STRING_MENU',
          'STRING_MODESWITCH',
          'STRING_NEXT',
          'STRING_PAGEDOWN',
          'STRING_PAGEUP',
          'STRING_PAUSE',
          'STRING_PREV',
          'STRING_PRINT',
          'STRING_PRINTSCREEN',
          'STRING_REDO',
          'STRING_RESET',
          'STRING_RIGHTARROW',
          'STRING_SCROLLLOCK',
          'STRING_SELECT',
          'STRING_STOP',
          'STRING_SYSREQ',
          'STRING_SYSTEM',
          'STRING_UNDO',
          'STRING_UPARROW',
          'STRING_USER',
          'SUBTITLE',
          'T',
          'TAB',
          'U',
          'UP',
          'V',
          'VOD',
          'W',
          'X',
          'Y',
          'YELLOW',
          'Z',
          'CharCodeStrings'
        ])
      },
      native: {
        instance: {
          capsLock: desc(def, 'capsLock'),
          hasVirtualKeyboard: desc(def, 'hasVirtualKeyboard'),
          numLock: desc(def, 'numLock'),
          physicalKeyboardType: desc(def, 'physicalKeyboardType'),
          isAccessible: desc(def, 'isAccessible')
        }
      }
    };
    return def;
  }.call(this);
var MouseDefinition = function () {
    var def = {
        __class__: 'flash.ui.Mouse'
      };
    function hide() {
    }
    function show() {
    }
    function registerCursor() {
      notImplemented();
    }
    function unregisterCursor() {
      notImplemented();
    }
    def.__glue__ = {
      native: {
        static: {
          cursor: {
            get: function () {
              return 'auto';
            },
            set: function () {
              notImplemented();
            }
          },
          supportsCursor: {
            get: function () {
              return true;
            }
          },
          supportsNativeCursor: {
            get: function () {
              return true;
            }
          },
          hide: hide,
          show: show,
          registerCursor: registerCursor,
          unregisterCursor: unregisterCursor
        }
      }
    };
    return def;
  }.call(this);
var MouseCursorDataDefinition = function () {
    return {
      __class__: 'flash.ui.MouseCursorData',
      initialize: function () {
      },
      __glue__: {
        native: {
          static: {},
          instance: {
            data: {
              get: function data() {
                notImplemented('MouseCursorData.data');
                return this._data;
              },
              set: function data(data) {
                notImplemented('MouseCursorData.data');
                this._data = data;
              }
            },
            hotSpot: {
              get: function hotSpot() {
                notImplemented('MouseCursorData.hotSpot');
                return this._hotSpot;
              },
              set: function hotSpot(data) {
                notImplemented('MouseCursorData.hotSpot');
                this._hotSpot = data;
              }
            },
            frameRate: {
              get: function frameRate() {
                notImplemented('MouseCursorData.frameRate');
                return this._frameRate;
              },
              set: function frameRate(data) {
                notImplemented('MouseCursorData.frameRate');
                this._frameRate = data;
              }
            }
          }
        }
      }
    };
  }.call(this);
{
  var DictionaryDefinition = function () {
      return {
        __class__: 'flash.utils.Dictionary',
        initialize: function () {
        },
        __glue__: {
          native: {
            static: {},
            instance: {
              init: function init(weakKeys) {
                notImplemented('Dictionary.init');
              }
            }
          }
        }
      };
    }.call(this);
}
var TimerDefinition = function () {
    var def = {
        __class__: 'flash.utils.Timer',
        initialize: function () {
          this._running = false;
        }
      };
    def.__glue__ = {
      native: {
        instance: {
          running: {
            get: function () {
              return this._running;
            }
          },
          _start: function (delay, closure) {
            this._running = true;
            this.interval = setInterval(closure, delay);
          },
          stop: function () {
            this._running = false;
            clearInterval(this.interval);
          },
          _tick: function () {
            if (!this._running) {
              return;
            }
            this._dispatchEvent(new flash.events.TimerEvent('timer', true, false));
          }
        }
      }
    };
    return def;
  }.call(this);
{
  var AccessibilityDefinition = function () {
      return {
        __class__: 'flash.accessibility.Accessibility',
        initialize: function () {
        },
        __glue__: {
          native: {
            static: {
              sendEvent: function sendEvent(source, childID, eventType, nonHTML) {
                notImplemented('Accessibility.sendEvent');
              },
              updateProperties: function updateProperties() {
                notImplemented('Accessibility.updateProperties');
              },
              active: {
                get: function active() {
                  somewhatImplemented('Accessibility.active');
                  return false;
                }
              }
            },
            instance: {}
          }
        }
      };
    }.call(this);
}
{
  var AS2ButtonDefinition = function () {
      var def = {
          __class__: 'avm1lib.AS2Button',
          initialize: function () {
          }
        };
      var desc = Object.getOwnPropertyDescriptor;
      def.__glue__ = {
        native: {
          instance: {
            _as3Object: {
              get: function () {
                return this.$nativeObject;
              }
            },
            _init: function init(nativeButton) {
              Object.defineProperty(this, '$nativeObject', {
                value: nativeButton
              });
              nativeButton.$as2Object = this;
              initDefaultListeners(this);
            }
          }
        },
        script: {
          instance: Glue.ALL
        }
      };
      return def;
    }.call(this);
}
var AS2GlobalsDefinition = function () {
    var def = {
        __class__: 'avm1lib.AS2Globals',
        initialize: function () {
          flash.text.TextFormat.prototype.asDefinePublicProperty('getTextExtent', {
            value: TextFormatDefinition.as2GetTextExtent,
            writable: false,
            enumerable: false,
            configurable: false
          });
        }
      };
    def.__glue__ = {
      native: {
        instance: {
          ASSetPropFlags: function ASSetPropFlags(obj, children, flags, allowFalse) {
          },
          _addToPendingScripts: function _addToPendingScripts(subject, fn, args) {
            AS2Context.instance.addToPendingScripts(function () {
              fn.apply(subject, args);
            });
          },
          _setLevel: function _setLevel(level, loader) {
            AS2Context.instance.stage._as2SetLevel(level, loader);
          },
          trace: function (expression) {
            var trace = avm2.applicationDomain.getProperty(Multiname.fromSimpleName('trace'), true, true);
            trace(expression);
          }
        },
        static: {
          _addInternalClasses: function _addInternalClasses(proto) {
            proto.asSetPublicProperty('Object', Stubs.Object);
            proto.asSetPublicProperty('Function', Stubs.Function);
            proto.asSetPublicProperty('Array', Stubs.Array);
            proto.asSetPublicProperty('Number', Stubs.Number);
            proto.asSetPublicProperty('Math', avm2.systemDomain.getClass('Math'));
            proto.asSetPublicProperty('Boolean', Stubs.Boolean);
            proto.asSetPublicProperty('Date', Stubs.Date);
            proto.asSetPublicProperty('RegExp', Stubs.RegExp);
            proto.asSetPublicProperty('String', Stubs.String);
          }
        }
      },
      script: {
        instance: Glue.ALL
      }
    };
    return def;
  }.call(this);
var AS2MovieClipDefinition = function () {
    var def = {
        __class__: 'avm1lib.AS2MovieClip',
        initialize: function () {
        },
        _insertChildAtDepth: function _insertChildAtDepth(mc, depth) {
          return this.$nativeObject._insertChildAtDepth(mc, depth);
        },
        _duplicate: function _duplicate(name, depth, initObject) {
          return this.$nativeObject._duplicate(name, depth, initObject);
        },
        _constructSymbol: function constructSymbol(symbolId, name) {
          var theClass = AS2Context.instance.classes && AS2Context.instance.classes[symbolId];
          var symbolProps = AS2Context.instance.assets[symbolId];
          var symbolClass = flash.display.MovieClip.class;
          var mc = symbolClass.createAsSymbol(symbolProps);
          mc._avm1SymbolClass = theClass;
          symbolClass.instanceConstructor.call(mc);
          this.$nativeObject.addChild(mc);
          return mc;
        },
        _gotoLabel: function (label) {
          this.$nativeObject.gotoLabel(label);
        },
        _callFrame: function callFrame(frame) {
          this.$nativeObject._callFrame(frame);
        },
        init: function init(nativeMovieClip) {
          if (!nativeMovieClip) {
            return;
          }
          Object.defineProperty(this, '$nativeObject', {
            value: nativeMovieClip
          });
          nativeMovieClip.$as2Object = this;
          initDefaultListeners(this);
        }
      };
    var desc = Object.getOwnPropertyDescriptor;
    def.__glue__ = {
      native: {
        instance: {
          _as3Object: {
            get: function () {
              return this.$nativeObject;
            }
          },
          _init: def.init,
          _insertChildAtDepth: def._insertChildAtDepth,
          _duplicate: def._duplicate,
          _constructSymbol: def._constructSymbol,
          _callFrame: def._callFrame,
          _gotoLabel: def._gotoLabel
        }
      },
      script: {
        instance: Glue.ALL
      }
    };
    return def;
  }.call(this);
var AS2MovieClipLoaderDefinition = function () {
    var def = {
        __class__: 'avm1lib.AS2MovieClipLoader',
        initialize: function () {
        },
        get _bytesLoaded() {
          return this.$nativeObject._contentLoaderInfo._bytesLoaded;
        }
      };
    var desc = Object.getOwnPropertyDescriptor;
    def.__glue__ = {
      native: {
        instance: {
          $nativeObject: {
            get: function () {
              return this.$nativeObject;
            }
          },
          _bytesLoaded: desc(def, '_bytesLoaded')
        }
      },
      script: {
        instance: Glue.ALL
      }
    };
    return def;
  }.call(this);
var AS2TextFieldDefinition = function () {
    var def = {
        __class__: 'avm1lib.AS2TextField',
        initialize: function () {
          this._variable = '';
        }
      };
    def.__glue__ = {
      native: {
        instance: {
          variable: {
            get: function () {
              return this._variable;
            },
            set: function (name) {
              if (name === this._variable) {
                return;
              }
              this._variable = name;
              var instance = this.$nativeObject;
              var hasPath = name.indexOf('.') >= 0 || name.indexOf(':') >= 0;
              var clip;
              if (hasPath) {
                var targetPath = name.split(/[.:\/]/g);
                name = targetPath.pop();
                if (targetPath[0] == '_root' || targetPath[0] === '') {
                  clip = instance.root._getAS2Object();
                  targetPath.shift();
                  if (targetPath[0] === '') {
                    targetPath.shift();
                  }
                } else {
                  clip = instance._parent._getAS2Object();
                }
                while (targetPath.length > 0) {
                  var childName = targetPath.shift();
                  clip = clip.asGetPublicProperty(childName) || clip[childName];
                  if (!clip) {
                    throw new Error('Cannot find ' + childName + ' variable');
                  }
                }
              } else {
                clip = instance._parent._getAS2Object();
              }
              if (!clip.asHasProperty(undefined, name, 0)) {
                clip.asSetPublicProperty(name, instance.text);
              }
              instance._addEventListener('advanceFrame', function () {
                instance.text = '' + clip.asGetPublicProperty(name);
              });
            }
          },
          _as3Object: {
            get: function () {
              return this.$nativeObject;
            }
          },
          _init: function init(nativeTextField) {
            Object.defineProperty(this, '$nativeObject', {
              value: nativeTextField
            });
            nativeTextField.$as2Object = this;
            initDefaultListeners(this);
          }
        }
      },
      script: {
        instance: Glue.ALL
      }
    };
    return def;
  }.call(this);
var AS2UtilsDefinition = function () {
    var def = {
        __class__: 'avm1lib.AS2Utils',
        initialize: function () {
        }
      };
    function installObjectMethods() {
      var c = Stubs.Object, p = c.asGetPublicProperty('prototype');
      c.asSetPublicProperty('registerClass', function registerClass(name, theClass) {
        var classes = AS2Context.instance.classes || (AS2Context.instance.classes = {});
        classes[name] = theClass;
      });
      p.asDefinePublicProperty('addProperty', {
        value: function addProperty(name, getter, setter) {
          if (typeof name !== 'string' || name === '') {
            return false;
          }
          if (typeof getter !== 'function') {
            return false;
          }
          if (typeof setter !== 'function' && setter !== null) {
            return false;
          }
          this.asDefinePublicProperty(name, {
            get: getter,
            set: setter || undefined,
            configurable: true,
            enumerable: true
          });
          return true;
        },
        writable: false,
        enumerable: false,
        configurable: false
      });
    }
    def.__glue__ = {
      native: {
        static: {
          getAS2Object: function (nativeObject) {
            return nativeObject && nativeObject._getAS2Object ? nativeObject._getAS2Object() : null;
          },
          addProperty: function (obj, propertyName, getter, setter, enumerable) {
            obj.asDefinePublicProperty(propertyName, {
              get: getter,
              set: setter || undefined,
              enumerable: enumerable,
              configurable: true
            });
          },
          resolveTarget: function (target_mc) {
            return AS2Context.instance.resolveTarget(target_mc);
          },
          resolveLevel: function (level) {
            return AS2Context.instance.resolveLevel(level);
          },
          currentStage: {
            get: function () {
              return AS2Context.instance.stage;
            }
          },
          _installObjectMethods: installObjectMethods
        }
      }
    };
    return def;
  }.call(this);
function initDefaultListeners(thisArg) {
  var defaultListeners = thisArg.asGetPublicProperty('$defaultListeners');
  if (!defaultListeners) {
    return;
  }
  for (var i = 0; i < defaultListeners.length; i++) {
    var p = defaultListeners[i];
    p.asGetPublicProperty('setter').call(thisArg, p.value);
  }
}
function bindNativeClassDefinition(nativeName, definition) {
  natives[nativeName] = function (domain, scope, instanceConstructor, baseClass) {
    var c = new Class(undefined, instanceConstructor, ApplicationDomain.coerceCallable);
    c.extend(baseClass);
    c.linkNatives(definition);
    return c;
  };
}
var Stubs = new function () {
    var that = this;
    var definitions = createEmptyObject();
    var DEFAULT_DEFINITION = {
        __glue__: {
          script: {
            instance: Glue.ALL,
            static: Glue.ALL
          }
        }
      };
    this.getClassNames = function () {
      return Object.keys(definitions);
    };
    this.onClassCreated = function (eventType, cls) {
      var classOriginalName = cls.classInfo.instanceInfo.name.getOriginalName();
      if (classOriginalName in definitions) {
        cls.link(definitions[classOriginalName] || DEFAULT_DEFINITION);
      }
    };
    function makeStub(container, classSimpleName, shortName) {
      Object.defineProperty(container, shortName, {
        get: function () {
          var cls = avm2.systemDomain.getClass(classSimpleName);
          true;
          Object.defineProperty(container, shortName, {
            value: cls.instanceConstructor,
            writable: false
          });
          return container[shortName];
        },
        configurable: true
      });
    }
    [
      'Boolean',
      'Date',
      'String',
      'Function',
      'Object',
      'Number',
      'Math',
      'Array',
      'RegExp'
    ].forEach(function (classSimpleName) {
      makeStub(that, classSimpleName, classSimpleName);
    });
    [
      'Error',
      'DefinitionError',
      'EvalError',
      'RangeError',
      'ReferenceError',
      'SecurityError',
      'SyntaxError',
      'TypeError',
      'URIError',
      'VerifyError',
      'UninitializedError',
      'ArgumentError'
    ].forEach(function (classSimpleName) {
      makeStub(that, classSimpleName, classSimpleName);
    });
    function M(classSimpleName, nativeName, definition) {
      return {
        classSimpleName: classSimpleName,
        nativeName: nativeName,
        definition: definition
      };
    }
    [
      M('flash.display.DisplayObject', 'DisplayObjectClass', DisplayObjectDefinition),
      M('flash.display.InteractiveObject', 'InteractiveObjectClass', InteractiveObjectDefinition),
      M('flash.display.DisplayObjectContainer', 'ContainerClass', DisplayObjectContainerDefinition),
      M('flash.display.Sprite', 'SpriteClass', SpriteDefinition),
      M('flash.display.MovieClip', 'MovieClipClass', MovieClipDefinition),
      M('flash.display.Shape', 'ShapeClass', ShapeDefinition),
      M('flash.display.Bitmap', 'BitmapClass', BitmapDefinition),
      M('flash.display.BitmapData', 'BitmapDataClass', BitmapDataDefinition),
      M('flash.display.Stage', 'StageClass', StageDefinition),
      M('flash.display.Loader', 'LoaderClass', LoaderDefinition),
      M('flash.display.LoaderInfo', 'LoaderInfoClass', LoaderInfoDefinition),
      M('flash.display.Graphics', 'GraphicsClass', GraphicsDefinition),
      M('flash.display.SimpleButton', 'SimpleButtonClass', SimpleButtonDefinition),
      M('flash.display.MorphShape', 'MorphShapeClass', MorphShapeDefinition),
      M('flash.display.NativeMenu', 'MenuClass', NativeMenuDefinition),
      M('flash.display.NativeMenuItem', 'MenuItemClass', NativeMenuItemDefinition),
      M('flash.display.FrameLabel', 'FrameLabelClass', FrameLabelDefinition),
      M('flash.display.Scene'),
      M('flash.display.BlendMode'),
      M('flash.display.Shader', 'ShaderClass', ShaderDefinition),
      M('flash.display.ShaderData', 'ShaderDataClass', ShaderDataDefinition),
      M('flash.filters.BevelFilter', 'BevelFilterClass', BevelFilterDefinition),
      M('flash.filters.BitmapFilter', 'BitmapFilterClass', BitmapFilterDefinition),
      M('flash.filters.BlurFilter', 'BlurFilterClass', BlurFilterDefinition),
      M('flash.filters.ColorMatrixFilter', 'ColorMatrixFilterClass', ColorMatrixFilterDefinition),
      M('flash.filters.ConvolutionFilter', 'ConvolutionFilterClass', ConvolutionFilterDefinition),
      M('flash.filters.DisplacementMapFilter', 'DisplacementMapFilterClass', DisplacementMapFilterDefinition),
      M('flash.filters.DropShadowFilter', 'DropShadowFilterClass', DropShadowFilterDefinition),
      M('flash.filters.GlowFilter', 'GlowFilterClass', GlowFilterDefinition),
      M('flash.filters.GradientBevelFilter', 'GradientBevelFilterClass', GradientBevelFilterDefinition),
      M('flash.filters.GradientGlowFilter', 'GradientGlowFilterClass', GradientGlowFilterDefinition),
      M('flash.filters.ShaderFilter', 'ShaderFilterClass', ShaderFilterDefinition),
      M('flash.geom.Point', 'PointClass', PointDefinition),
      M('flash.geom.Rectangle', 'RectangleClass', RectangleDefinition),
      M('flash.geom.Matrix', 'MatrixClass', MatrixDefinition),
      M('flash.geom.Matrix3D', 'Matrix3DClass', Matrix3DDefinition),
      M('flash.geom.Vector3D', 'Vector3DClass', Vector3DDefinition),
      M('flash.geom.Transform', 'TransformClass', TransformDefinition),
      M('flash.geom.ColorTransform', 'ColorTransformClass', ColorTransformDefinition),
      M('flash.events.EventDispatcher', 'EventDispatcherClass', EventDispatcherDefinition),
      M('flash.events.Event', 'EventClass', EventDefinition),
      M('flash.events.IOErrorEvent'),
      M('flash.events.NetStatusEvent'),
      M('flash.events.KeyboardEvent', 'KeyboardEventClass', KeyboardEventDefinition),
      M('flash.events.MouseEvent', 'MouseEventClass', MouseEventDefinition),
      M('flash.events.TextEvent', 'TextEventClass', TextEventDefinition),
      M('flash.events.TimerEvent', 'TimerEventClass', TimerEventDefinition),
      M('flash.events.ProgressEvent'),
      M('flash.events.NetStatusEvent'),
      M('flash.external.ExternalInterface', 'ExternalInterfaceClass', ExternalInterfaceDefinition),
      M('flash.ui.ContextMenu', 'ContextMenuClass', ContextMenuDefinition),
      M('flash.ui.ContextMenuItem', 'ContextMenuItemClass', ContextMenuItemDefinition),
      M('flash.ui.Keyboard', 'KeyboardClass', KeyboardDefinition),
      M('flash.ui.Mouse', 'MouseClass', MouseDefinition),
      M('flash.ui.MouseCursorData', 'MouseCursorDataClass', MouseCursorDataDefinition),
      M('flash.text.Font', 'FontClass', FontDefinition),
      M('flash.text.TextField', 'TextFieldClass', TextFieldDefinition),
      M('flash.text.StaticText', 'StaticTextClass', StaticTextDefinition),
      M('flash.text.StyleSheet', 'StyleSheetClass', StyleSheetDefinition),
      M('flash.text.TextFormat', 'TextFormatClass', TextFormatDefinition),
      M('flash.text.TextLineMetrics'),
      M('flash.text.engine.ContentElement', 'ContentElementClass', ContentElementDefinition),
      M('flash.text.engine.ElementFormat', 'ElementFormatClass', ElementFormatDefinition),
      M('flash.text.engine.FontDescription', 'FontDescriptionClass', FontDescriptionDefinition),
      M('flash.text.engine.GroupElement', 'GroupElementClass', GroupElementDefinition),
      M('flash.text.engine.SpaceJustifier', 'SpaceJustifierClass', SpaceJustifierDefinition),
      M('flash.text.engine.TextBlock', 'TextBlockClass', TextBlockDefinition),
      M('flash.text.engine.TextElement', 'TextElementClass', TextElementDefinition),
      M('flash.text.engine.TextJustifier', 'TextJustifierClass', TextJustifierDefinition),
      M('flash.text.engine.TextLine', 'TextLineClass', TextLineDefinition),
      M('flash.media.Sound', 'SoundClass', SoundDefinition),
      M('flash.media.SoundChannel', 'SoundChannelClass', SoundChannelDefinition),
      M('flash.media.SoundMixer', 'SoundMixerClass', SoundMixerDefinition),
      M('flash.media.SoundTransform', 'SoundTransformClass', SoundTransformDefinition),
      M('flash.media.Video', 'VideoClass', VideoDefinition),
      M('flash.media.ID3Info', 'ID3InfoClass', ID3InfoDefinition),
      M('flash.media.Microphone', 'MicrophoneClass', MicrophoneDefinition),
      M('flash.net.FileFilter', 'FileFilterClass', FileFilterDefinition),
      M('flash.net.NetConnection', 'NetConnectionClass', NetConnectionDefinition),
      M('flash.net.NetStream', 'NetStreamClass', NetStreamDefinition),
      M('flash.net.Responder', 'ResponderClass', ResponderDefinition),
      M('flash.net.URLRequest', 'URLRequestClass', URLRequestDefinition),
      M('flash.net.URLStream', 'URLStreamClass', URLStreamDefinition),
      M('flash.net.URLLoader', 'URLLoaderClass', URLLoaderDefinition),
      M('flash.net.SharedObject', 'SharedObjectClass', SharedObjectDefinition),
      M('flash.net.ObjectEncoding', 'ObjectEncodingClass', ObjectEncodingDefinition),
      M('flash.net.LocalConnection', 'LocalConnectionClass', LocalConnectionDefinition),
      M('flash.net.Socket', 'SocketClass', SocketDefinition),
      M('flash.net.URLVariables'),
      M('packageInternal flash.system.FSCommand', 'FSCommandClass', FSCommandDefinition),
      M('flash.system.Capabilities', 'CapabilitiesClass', CapabilitiesDefinition),
      M('flash.system.System', 'SystemClass', SystemDefinition),
      M('flash.system.Security', 'SecurityClass', SecurityDefinition),
      M('flash.system.SecurityDomain', 'SecurityDomainClass', SecurityDomainDefinition),
      M('flash.system.ApplicationDomain', 'ApplicationDomainClass', ApplicationDomainDefinition),
      M('flash.accessibility.Accessibility', 'AccessibilityClass', AccessibilityDefinition),
      M('flash.utils.Timer', 'TimerClass', TimerDefinition),
      M('avm1lib.AS2Utils', 'AS2Utils', AS2UtilsDefinition),
      M('avm1lib.AS2Broadcaster'),
      M('avm1lib.AS2Key'),
      M('avm1lib.AS2Mouse'),
      M('avm1lib.AS2MovieClip', 'AS2MovieClip', AS2MovieClipDefinition),
      M('avm1lib.AS2Button', 'AS2Button', AS2ButtonDefinition),
      M('avm1lib.AS2TextField', 'AS2TextField', AS2TextFieldDefinition),
      M('avm1lib.AS2Stage'),
      M('avm1lib.AS2System'),
      M('avm1lib.AS2Color'),
      M('avm1lib.AS2Globals', 'AS2Globals', AS2GlobalsDefinition),
      M('avm1lib.AS2MovieClipLoader', 'AS2MovieClipLoader', AS2MovieClipLoaderDefinition)
    ].forEach(function (m) {
      var className = Multiname.fromSimpleName(m.classSimpleName);
      var path = className.getOriginalName().split('.');
      var container = this;
      for (var i = 0, j = path.length - 1; i < j; i++) {
        if (!container[path[i]]) {
          container[path[i]] = {};
        }
        container = container[path[i]];
      }
      makeStub(container, m.classSimpleName, path[path.length - 1]);
      if (m.nativeName) {
        bindNativeClassDefinition(m.nativeName, m.definition);
      }
      definitions[className.getOriginalName()] = m.definition;
    });
  }();
natives['FlashUtilScript::getAliasName'] = function (domain, scope, instanceConstructor, baseClass) {
  return function getAliasName(value) {
    return value.debugName;
  };
};
natives['FlashUtilScript::getDefinitionByName'] = natives.getDefinitionByName;
natives['FlashUtilScript::getTimer'] = function GetTimerMethod(domain, scope, instanceConstructor, baseClass) {
  var start = Date.now();
  return function getTimer() {
    return Date.now() - start;
  };
};
natives['FlashUtilScript::escapeMultiByte'] = function EscapeMultiByteMethod(domain, scope, instanceConstructor, baseClass) {
  return escape;
};
natives['FlashUtilScript::unescapeMultiByte'] = function UnescapeMultiByteMethod(domain, scope, instanceConstructor, baseClass) {
  return unescape;
};
natives['FlashNetScript::navigateToURL'] = function GetNavigateToURLMethod(domain, scope, instanceConstructor, baseClass) {
  return function navigateToURL(request, window_) {
    if (request === null || request === undefined) {
      throwError('TypeError', Errors.NullPointerError, 'request');
    }
    var RequestClass = avm2.systemDomain.getClass('flash.net.URLRequest');
    if (!RequestClass.isInstanceOf(request)) {
      throwError('TypeError', Errors.CheckTypeFailedError, request, 'flash.net.URLRequest');
    }
    var url = request.url;
    if (/^fscommand:/i.test(url)) {
      var fscommand = avm2.applicationDomain.getProperty(Multiname.fromSimpleName('flash.system.fscommand'), true, true);
      fscommand.call(null, url.substring('fscommand:'.length), window_);
      return;
    }
    var targetWindow = window_ || '_parent';
    window.open(FileLoadingService.resolveUrl(url), targetWindow);
  };
};
natives['FlashNetScript::sendToURL'] = function GetSendToURLMethod(domain, scope, instanceConstructor, baseClass) {
  return function sendToURL(request) {
    if (request === null || request === undefined) {
      throwError('TypeError', Errors.NullPointerError, 'request');
    }
    var RequestClass = avm2.systemDomain.getClass('flash.net.URLRequest');
    if (!RequestClass.isInstanceOf(request)) {
      throwError('TypeError', Errors.CheckTypeFailedError, request, 'flash.net.URLRequest');
    }
    var session = FileLoadingService.createSession();
    session.onprogress = function () {
    };
    session.open(request);
  };
};
natives['Toplevel::registerClassAlias'] = function GetRegisterClassAliasMethod(domain, scope, instance, baseClass) {
  return function registerClassAlias(aliasName, classObject) {
    if (!aliasName) {
      throwError('TypeError', Errors.NullPointerError, 'aliasName');
    }
    if (!classObject) {
      throwError('TypeError', Errors.NullPointerError, 'classObject');
    }
    AMFUtils.aliasesCache.classes.set(classObject, aliasName);
    AMFUtils.aliasesCache.names[aliasName] = classObject;
  };
};
natives['Toplevel::getClassByAlias'] = function GetGetClassByAliasMethod(domain, scope, instance, baseClass) {
  return function getClassByAlias(aliasName) {
    if (!aliasName) {
      throwError('TypeError', Errors.NullPointerError, 'aliasName');
    }
    var classObject = AMFUtils.aliasesCache.names[aliasName];
    if (!classObject) {
      throwError('ReferenceError', Errors.ClassNotFoundError, aliasName);
    }
    return classObject;
  };
};
