Backed out changeset 41143dba70eb (bug 962736) for xperf regressions.
authorRyan VanderMeulen <ryanvm@gmail.com>
Fri, 24 Jan 2014 09:50:16 -0500
changeset 181122 861d0354e018aeca4bc3ccedc1b245a4ba32b1ec
parent 181121 801cab0388a24c2da67a63b98193a9cb95c2854b
child 181123 7c5e60cbcc95228516dc580d9b1247f6d9a558b5
push id3343
push userffxbld
push dateMon, 17 Mar 2014 21:55:32 +0000
treeherdermozilla-beta@2f7d3415f79f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs962736
milestone29.0a1
backs out41143dba70eb8c00da3a96088366280be93d60be
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset 41143dba70eb (bug 962736) for xperf regressions.
browser/extensions/shumway/content/ShumwayStreamConverter.jsm
browser/extensions/shumway/content/shumway-worker.js
browser/extensions/shumway/content/shumway.js
browser/extensions/shumway/content/version.txt
browser/extensions/shumway/content/web/avm-sandbox.js
browser/extensions/shumway/content/web/viewer.html
--- a/browser/extensions/shumway/content/ShumwayStreamConverter.jsm
+++ b/browser/extensions/shumway/content/ShumwayStreamConverter.jsm
@@ -32,40 +32,28 @@ const EXPECTED_PLAYPREVIEW_URI_PREFIX = 
 const FIREFOX_ID = '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}';
 const SEAMONKEY_ID = '{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}';
 
 const MAX_CLIPBOARD_DATA_SIZE = 8000;
 
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 Cu.import('resource://gre/modules/Services.jsm');
 Cu.import('resource://gre/modules/NetUtil.jsm');
-Cu.import("resource://gre/modules/AddonManager.jsm");
-
-var shumwayVersion;
-try {
-  AddonManager.getAddonByID("shumway@research.mozilla.org", function(addon) {
-    shumwayVersion = addon.version;
-  });
-} catch (ignored) {
-
-}
 
 XPCOMUtils.defineLazyModuleGetter(this, 'PrivateBrowsingUtils',
   'resource://gre/modules/PrivateBrowsingUtils.jsm');
 
 XPCOMUtils.defineLazyModuleGetter(this, 'ShumwayTelemetry',
   'resource://shumway/ShumwayTelemetry.jsm');
 
+let appInfo = Cc['@mozilla.org/xre/app-info;1'].getService(Ci.nsIXULAppInfo);
 let Svc = {};
 XPCOMUtils.defineLazyServiceGetter(Svc, 'mime',
                                    '@mozilla.org/mime;1', 'nsIMIMEService');
 
-let StringInputStream = Cc["@mozilla.org/io/string-input-stream;1"];
-let MimeInputStream = Cc["@mozilla.org/network/mime-input-stream;1"];
-
 function getBoolPref(pref, def) {
   try {
     return Services.prefs.getBoolPref(pref);
   } catch (ex) {
     return def;
   }
 }
 
@@ -195,33 +183,16 @@ function isShumwayEnabledFor(actions) {
     /sndcdn\.com\/assets\/swf/.test(url) /* soundcloud */ ||
     /vimeocdn\.com/.test(url) /* vimeo */) {
     return false;
   }
 
   return true;
 }
 
-function getVersionInfo() {
-  var versionInfo = {
-    geckoMstone : 'unknown',
-    geckoBuildID: 'unknown',
-    shumwayVersion: 'unknown'
-  };
-  try {
-    versionInfo.geckoMstone = Services.prefs.getCharPref('gecko.mstone');
-    versionInfo.geckoBuildID = Services.prefs.getCharPref('gecko.buildID');
-    versionInfo.shumwayVersion = shumwayVersion;
-  } catch (e) {
-    console.warn('Error encountered while getting platform and shumway ' +
-                 'version info:', e);
-  }
-  return versionInfo;
-}
-
 function fallbackToNativePlugin(window, userAction, activateCTP) {
   var obj = window.frameElement;
   var doc = obj.ownerDocument;
   var e = doc.createEvent("CustomEvent");
   e.initCustomEvent("MozPlayPlugin", true, true, activateCTP);
   obj.dispatchEvent(e);
 
   ShumwayTelemetry.onFallback(userAction);
@@ -390,17 +361,17 @@ ChromeActions.prototype = {
       } else {
         log("data access id prohibited to " + url + " from " + baseUrl);
         win.postMessage({callback:"loadFile", sessionId: sessionId, topic: "error",
           error: "only original swf file or file from the same origin loading supported"}, "*");
       }
     });
   },
   fallback: function(automatic) {
-    automatic = !!automatic;
+    automatic = !!automatic; // cast to boolean
     fallbackToNativePlugin(this.window, !automatic, automatic);
   },
   setClipboard: function (data) {
     if (typeof data !== 'string' ||
         data.length > MAX_CLIPBOARD_DATA_SIZE ||
         !this.document.hasFocus()) {
       return;
     }
@@ -456,36 +427,16 @@ ChromeActions.prototype = {
       if (errorType >= MIN_ERROR_TYPE && errorType <= MAX_ERROR_TYPE &&
           !this.telemetry.errors[errorType]) {
         this.telemetry.errors[errorType] = true; // record only one report per SWF
         ShumwayTelemetry.onError(errorType);
       }
       break;
     }
   },
-  reportIssue: function(exceptions) {
-    var base = "http://shumway-issue-reporter.paas.allizom.org/input?";
-    var windowUrl = this.window.parent.wrappedJSObject.location + '';
-    var params = 'url=' + encodeURIComponent(windowUrl);
-    params += '&swf=' + encodeURIComponent(this.url);
-    var versions = getVersionInfo();
-    params += '&ffbuild=' + encodeURIComponent(versions.geckoMstone + ' (' +
-                                               versions.geckoBuildID + ')');
-    params += '&shubuild=' + encodeURIComponent(versions.shumwayVersion);
-    var postDataStream = StringInputStream.
-                         createInstance(Ci.nsIStringInputStream);
-    postDataStream.data = 'exceptions=' + encodeURIComponent(exceptions);
-    var postData = MimeInputStream.createInstance(Ci.nsIMIMEInputStream);
-    postData.addHeader("Content-Type", "application/x-www-form-urlencoded");
-    postData.addContentLength = true;
-    postData.setData(postDataStream);
-    this.window.openDialog('chrome://browser/content', '_blank',
-                           'all,dialog=no', base + params, null, null,
-                           postData);
-  },
   externalCom: function (data) {
     if (!this.allowScriptAccess)
       return;
 
     // TODO check security ?
     var parentWindow = this.window.parent.wrappedJSObject;
     var embedTag = this.embedTag.wrappedJSObject;
     switch (data.action) {
@@ -503,19 +454,16 @@ ChromeActions.prototype = {
       return parentWindow.__flash__eval(data.expression);
     case 'call':
       return parentWindow.__flash__call(data.request);
     case 'register':
       return embedTag.__flash__registerCallback(data.functionName);
     case 'unregister':
       return embedTag.__flash__unregisterCallback(data.functionName);
     }
-  },
-  getWindowUrl: function() {
-    return this.window.parent.wrappedJSObject.location + '';
   }
 };
 
 // Event listener to trigger chrome privedged code.
 function RequestListener(actions) {
   this.actions = actions;
 }
 // Receive an event and synchronously or asynchronously responds.
--- a/browser/extensions/shumway/content/shumway-worker.js
+++ b/browser/extensions/shumway/content/shumway-worker.js
@@ -3870,23 +3870,16 @@ function createParsingContext(commitData
           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;
@@ -5815,17 +5808,17 @@ var readHeader = function readHeader($by
   $.frameRate = readUi8($bytes, $stream) + frameRateFraction / 256;
   $.frameCount = readUi16($bytes, $stream);
   return $;
 };
 (function (global) {
   global['tagHandler'] = tagHandler;
   global['readHeader'] = readHeader;
 }(this));
-function readTags(context, stream, swfVersion, final, onprogress, onexception) {
+function readTags(context, stream, swfVersion, final, onprogress) {
   var tags = context.tags;
   var bytes = stream.bytes;
   var lastSuccessfulPosition;
   var tag = null;
   if (context._readTag) {
     tag = context._readTag;
     delete context._readTag;
   }
@@ -5884,17 +5877,16 @@ function readTags(context, stream, swfVe
       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;
@@ -6044,17 +6036,17 @@ BodyParser.prototype = {
     }
     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);
+    readTags(swf, stream, swfVersion, finalBlock, options.onprogress);
     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);
     }
   }
--- a/browser/extensions/shumway/content/shumway.js
+++ b/browser/extensions/shumway/content/shumway.js
@@ -5016,20 +5016,33 @@ var disableRenderVisitor = rendererOptio
 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', true, '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'));
+if (typeof FirefoxCom !== 'undefined') {
+  turboMode.value = FirefoxCom.requestSync('getBoolPref', {
+    pref: 'shumway.turboMode',
+    def: false
+  });
+  hud.value = FirefoxCom.requestSync('getBoolPref', {
+    pref: 'shumway.hud',
+    def: false
+  });
+  forceHidpi.value = FirefoxCom.requestSync('getBoolPref', {
+    pref: 'shumway.force_hidpi',
+    def: false
+  });
+}
 var CanvasCache = {
     cache: [],
     getCanvas: function getCanvas(protoCanvas) {
       var tempCanvas = this.cache.shift();
       if (!tempCanvas) {
         tempCanvas = {
           canvas: document.createElement('canvas')
         };
@@ -5415,17 +5428,23 @@ function RenderingContext(refreshStage, 
   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 (m.a * m.d == m.b * m.c) {
+      ctx.closePath();
+      ctx.rect(0, 0, 0, 0);
+      ctx.clip();
+    } else {
+      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;
     }
@@ -5522,67 +5541,21 @@ function initializeHUD(stage, parentCanv
   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;
@@ -5630,27 +5603,78 @@ function renderStage(stage, ctx, events)
     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 frameTime = 0;
+  var maxDelay = 1000 / stage._frameRate;
+  var nextRenderAt = performance.now();
   var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || window.setTimeout;
-  var renderDummyBalls = dummyAnimation.value && createRenderDummyBalls(ctx, stage);
+  var renderDummyBalls;
+  var dummyBalls;
+  if (typeof FirefoxCom !== 'undefined' && FirefoxCom.requestSync('getBoolPref', {
+      pref: 'shumway.dummyMode',
+      def: false
+    })) {
+    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);
+    renderDummyBalls = function () {
+      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;
+      });
+    };
+  }
   console.timeEnd('Initialize Renderer');
   console.timeEnd('Total');
   var firstRun = true;
   var frameCount = 0;
   var frameFPSAverage = new metrics.Average(120);
-  var frameRequested = true;
-  function drawFrame(renderFrame, repaint) {
+  function drawFrame(renderFrame, frameRequested) {
+    if (!skipFrameDraw.value) {
+      frameRequested = true;
+    }
     sampleStart();
     var refreshStage = false;
     if (stage._invalid) {
       updateRenderTransform();
       stage._invalid = false;
       refreshStage = true;
     }
     var mouseMoved = false;
@@ -5679,24 +5703,17 @@ function renderStage(stage, ctx, events)
         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();
+      if (isCanvasVisible(ctx.canvas) && (refreshStage || renderFrame) && frameRequested) {
         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');
@@ -5709,17 +5726,16 @@ function renderStage(stage, ctx, events)
           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;
@@ -5736,154 +5752,74 @@ function renderStage(stage, ctx, events)
         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();
   }
+  var frameRequested = true;
+  var skipNextFrameDraw = false;
   (function draw() {
+    var now = performance.now();
     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);
+    frameTime = now;
+    if (renderFrame && renderDummyBalls) {
+      renderDummyBalls();
       return;
     }
-    frameScheduler.startFrame(stage._frameRate);
-    drawFrame(renderFrame, false);
-    frameScheduler.endFrame();
+    drawFrame(renderFrame, frameRequested && !skipNextFrameDraw);
     frameRequested = false;
-    if (!frameScheduler.isOnTime) {
-      traceRenderer.value && appendToFrameTerminal('Frame Is Late', 'red');
+    maxDelay = 1000 / stage._frameRate;
+    if (!turboMode.value) {
+      nextRenderAt += maxDelay;
+      var wasLate = false;
+      while (nextRenderAt < now) {
+        wasLate = true;
+        nextRenderAt += maxDelay;
+      }
+      if (wasLate && !skipNextFrameDraw) {
+        skipNextFrameDraw = true;
+        traceRenderer.value && appendToFrameTerminal('Skip Frame Draw', 'red');
+      } else {
+        skipNextFrameDraw = false;
+      }
+    } else {
+      nextRenderAt = now;
     }
     if (renderFrame && events.onAfterFrame) {
       events.onAfterFrame();
     }
     if (renderingTerminated) {
       if (events.onTerminated) {
         events.onTerminated();
       }
       return;
     }
-    setTimeout(draw, turboMode.value ? 0 : frameScheduler.nextFrameIn);
+    setTimeout(draw, Math.max(0, nextRenderAt - performance.now()));
   }());
   (function frame() {
     if (renderingTerminated) {
       return;
     }
+    if (stage._invalid || stage._mouseMoved) {
+      drawFrame(false, true);
+    }
     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) {
@@ -7304,17 +7240,17 @@ var readHeader = function readHeader($by
   $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) {
+function readTags(context, stream, swfVersion, final, onprogress) {
   var tags = context.tags;
   var bytes = stream.bytes;
   var lastSuccessfulPosition;
   var tag = null;
   if (context._readTag) {
     tag = context._readTag;
     delete context._readTag;
   }
@@ -7373,17 +7309,16 @@ function readTags(context, stream, swfVe
       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;
@@ -7533,17 +7468,17 @@ BodyParser.prototype = {
     }
     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);
+    readTags(swf, stream, swfVersion, finalBlock, options.onprogress);
     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);
     }
   }
@@ -7962,23 +7897,16 @@ function createParsingContext(commitData
           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;
@@ -9530,21 +9458,16 @@ function interpretActions(actionsData, s
           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 = {
@@ -24610,30 +24533,21 @@ var ApplicationDomain = function () {
         if (!this.base) {
           Type.initializeTypes(this);
         }
       },
       broadcastMessage: function (type, message, origin) {
         if (false) {
           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;
-        }
+        this.onMessage.notify1(type, {
+          data: message,
+          origin: origin,
+          source: this
+        });
         if (false) {
           Timer.stop();
         }
       },
       traceLoadedClasses: function (lastOnly) {
         var writer = new IndentingWriter();
         lastOnly || writer.enter('Loaded Classes And Interfaces');
         var classes = lastOnly ? [
@@ -33583,66 +33497,49 @@ var Interpreter = new (function () {
               throw e;
             }
           }
       }
     };
     return Interpreter;
   }())();
 var AVM2 = function () {
-    function findDefiningAbc(mn) {
-      if (!avm2.builtinsLoaded) {
-        return null;
-      }
-      for (var i = 0; i < mn.namespaces.length; i++) {
-        var name = mn.namespaces[i].originalURI + ':' + mn.name;
-        var abcName = playerGlobalNames[name];
-        if (abcName) {
-          break;
-        }
-      }
-      if (abcName) {
-        return grabAbc(abcName);
-      }
-      return null;
-    }
-    function avm2Ctor(sysMode, appMode, loadAVM1) {
+    function avm2(sysMode, appMode, findDefiningAbc, 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 = [];
-    }
-    avm2Ctor.currentAbc = function () {
+    }
+    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;
     };
-    avm2Ctor.currentDomain = function () {
+    avm2.currentDomain = function () {
       var abc = this.currentAbc();
       return abc.applicationDomain;
     };
-    avm2Ctor.prototype = {
+    avm2.prototype = {
       notifyConstruct: function notifyConstruct(instanceConstructor, args) {
       }
     };
-    return avm2Ctor;
+    return avm2;
   }();
 var playerGlobalNames = {};
 var playerGlobalScripts = {};
 (function () {
   var index = [
       {
         'name': 'Object',
         'offset': 0,
@@ -37034,21 +36931,38 @@ 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;
 }
+function findDefiningAbc(mn) {
+  if (!avm2.builtinsLoaded) {
+    return null;
+  }
+  var name;
+  for (var i = 0; i < mn.namespaces.length; i++) {
+    var name = mn.namespaces[i].originalURI + ':' + mn.name;
+    var abcName = playerGlobalNames[name];
+    if (abcName) {
+      break;
+    }
+  }
+  if (abcName) {
+    return grabAbc(abcName);
+  }
+  return null;
+}
 var avm2;
 var libraryScripts = playerGlobalScripts;
 var libraryNames = playerGlobalNames;
 function createAVM2(builtinPath, libraryPath, avm1Path, sysMode, appMode, next) {
-  avm2 = new AVM2(sysMode, appMode, loadAVM1);
+  avm2 = new AVM2(sysMode, appMode, findDefiningAbc, loadAVM1);
   var builtinAbc, libraryAbc, avm1Abc;
   new BinaryFileReader(libraryPath).readAll(null, function (buffer) {
     libraryAbcs = buffer;
     new BinaryFileReader(builtinPath).readAll(null, function (buffer) {
       builtinAbc = new AbcFile(new Uint8Array(buffer), 'builtin.abc');
       executeAbc();
     });
   });
@@ -37739,17 +37653,17 @@ var DisplayObjectDefinition = function (
                 }
                 node = nextNode;
               } while (node);
             }
           } else {
             m = this._concatenatedTransform;
           }
           if (targetCoordSpace && targetCoordSpace !== this._stage) {
-            m2 = targetCoordMatrix || targetCoordSpace._getConcatenatedTransform(null, false);
+            m2 = targetCoordMatrix || targetCoordSpace._getConcatenatedTransform();
             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);
@@ -37778,24 +37692,24 @@ var DisplayObjectDefinition = function (
               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 m = this._getConcatenatedTransform();
           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 m = this._getConcatenatedTransform();
           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) {
@@ -37826,17 +37740,17 @@ var DisplayObjectDefinition = function (
                     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)) {
+              if (child._hitTest && child._hitTest(true, x, y, true)) {
                 return true;
               }
             }
             return false;
           }
           var b1 = this.getBounds(this._stage);
           var b2 = hitTestObject.getBounds(hitTestObject._stage);
           x = Math.max(b1.xMin, b2.xMin);
@@ -38219,19 +38133,16 @@ var DisplayObjectDefinition = function (
               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);
@@ -38332,17 +38243,17 @@ var DisplayObjectDefinition = function (
           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 m = targetCoordSpace && !flash.display.DisplayObject.class.isInstanceOf(targetCoordSpace) ? targetCoordSpace : this._getConcatenatedTransform(targetCoordSpace);
           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;
@@ -39925,25 +39836,17 @@ var LoaderDefinition = function () {
           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);
-            }
+            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
               });
@@ -40535,20 +40438,62 @@ var MovieClipDefinition = function () {
             return this._framesLoaded;
           }
           return frameNum;
         },
         _registerStartSounds: function (frameNum, starts) {
           this._startSoundRegistrations[frameNum] = starts;
         },
         _initSoundStream: function (streamInfo) {
-          this._soundStream = new MovieClipSoundStream(streamInfo, this);
+          var soundStream = this._soundStream = {
+              data: {
+                sampleRate: streamInfo.sampleRate,
+                channels: streamInfo.channels
+              },
+              seekIndex: [],
+              position: 0
+            };
+          var isMP3 = streamInfo.format === 'mp3';
+          if (isMP3 && PLAY_USING_AUDIO_TAG) {
+            var element = document.createElement('audio');
+            if (element.canPlayType('audio/mpeg')) {
+              soundStream.element = element;
+              soundStream.rawFrames = [];
+              return;
+            }
+          }
+          soundStream.data.pcm = new Float32Array(streamInfo.samplesCount * streamInfo.channels);
+          if (isMP3) {
+            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);
+            };
+          }
         },
         _addSoundStreamBlock: function (frameNum, streamBlock) {
-          this._soundStream.appendBlock(frameNum, streamBlock);
+          var soundStream = this._soundStream;
+          var streamPosition = soundStream.position;
+          soundStream.seekIndex[frameNum] = streamPosition + streamBlock.seek * soundStream.data.channels;
+          soundStream.position = streamPosition + streamBlock.samplesCount * soundStream.data.channels;
+          if (soundStream.rawFrames) {
+            soundStream.rawFrames.push(streamBlock.data);
+            return;
+          }
+          var decoderSession = soundStream.decoderSession;
+          if (decoderSession) {
+            decoderSession.pushAsync(streamBlock.data);
+          } else {
+            soundStream.data.pcm.set(streamBlock.pcm, streamPosition);
+          }
         },
         _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];
@@ -40571,18 +40516,52 @@ var MovieClipDefinition = function () {
                 delete sound.channel;
               }
               if (!info.stop) {
                 var loops = info.hasLoops ? info.loopCount : 0;
                 sound.channel = sound.object.play(0, loops);
               }
             }
           }
-          if (this._soundStream) {
-            this._soundStream.playFrame(frameNum);
+          if (this._soundStream && !isNaN(this._soundStream.seekIndex[frameNum])) {
+            var PAUSE_WHEN_OF_SYNC_GREATER = 2;
+            var RESET_WHEN_OF_SYNC_GREATER = 4;
+            var soundStream = this._soundStream;
+            var element = soundStream.element;
+            if (element) {
+              var soundStreamData = soundStream.data;
+              var time = soundStream.seekIndex[frameNum] / soundStreamData.sampleRate / soundStreamData.channels;
+              if (this._complete && !soundStream.channel) {
+                var blob = new Blob(soundStream.rawFrames);
+                element.preload = 'metadata';
+                element.loop = false;
+                element.src = URL.createObjectURL(blob);
+                var symbolClass = flash.media.SoundChannel.class;
+                var channel = symbolClass.createAsSymbol({
+                    element: element
+                  });
+                symbolClass.instanceConstructor.call(channel);
+                soundStream.channel = channel;
+              } else if (!isNaN(element.duration) && element.currentTime > time + PAUSE_WHEN_OF_SYNC_GREATER && element.currentTime < time + RESET_WHEN_OF_SYNC_GREATER) {
+                element.pause();
+              } else if (!isNaN(element.duration) && (element.paused || Math.abs(element.currentTime - time) > RESET_WHEN_OF_SYNC_GREATER)) {
+                if (Math.abs(element.currentTime - time) > PAUSE_WHEN_OF_SYNC_GREATER) {
+                  element.pause();
+                  element.currentTime = time;
+                }
+                element.play();
+              }
+            } else if (!soundStream.sound) {
+              var symbolClass = flash.media.Sound.class;
+              var sound = symbolClass.createAsSymbol(this._soundStream.data);
+              symbolClass.instanceConstructor.call(sound);
+              var channel = sound.play();
+              soundStream.sound = sound;
+              soundStream.channel = channel;
+            }
           }
         },
         _getAS2Object: function () {
           if (!this.$as2Object) {
             if (this._avm1SymbolClass) {
               var nativeObject = this, nativeObjectClass = this._avm1SymbolClass;
               var constructWrapper = function () {
                 this.init(nativeObject);
@@ -40752,187 +40731,16 @@ var MovieClipDefinition = function () {
           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: {},
@@ -41709,17 +41517,17 @@ var StageDefinition = function () {
         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._qtree = new QuadTree(0, 0, this._stageWidth, this._stageHeight, 0);
         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;
@@ -42327,63 +42135,54 @@ var EventDispatcherDefinition = function
         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);
+        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 (event in mouseEvents) {
+                  event = new flash.events.MouseEvent(event, mouseEvents[event]);
+                  if (target._stage) {
+                    event._localX = target.mouseX;
+                    event._localY = target.mouseY;
+                  }
                 } else {
-                  if (event in mouseEvents) {
-                    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;
+                  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;
+          }
         }
       }
       return !event._stopPropagation;
     }
     return {
       __class__: 'flash.events.EventDispatcher',
       initialize: function () {
         this._target = this;
@@ -42543,25 +42342,25 @@ var MouseEventDefinition = function () {
       },
       __glue__: {
         native: {
           instance: {
             updateAfterEvent: function updateAfterEvent() {
             },
             getStageX: function getStageX() {
               if (this._target) {
-                var m = this._target._getConcatenatedTransform(null, false);
+                var m = this._target._getConcatenatedTransform();
                 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 m = this._target._getConcatenatedTransform();
                 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;
@@ -43477,17 +43276,17 @@ var TransformDefinition = function () {
           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);
+          var m = this._target._getConcatenatedTransform();
           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);
--- a/browser/extensions/shumway/content/version.txt
+++ b/browser/extensions/shumway/content/version.txt
@@ -1,2 +1,1 @@
-0.8.2
-17fa9cc
+0.7.933
--- a/browser/extensions/shumway/content/web/avm-sandbox.js
+++ b/browser/extensions/shumway/content/web/avm-sandbox.js
@@ -103,74 +103,48 @@ function runViewer() {
       var fid = s.split('/')[0];
       return fid !== '5' && fid !== '34' && fid !== '35'; // more?
     }).join(',');
   }
 
   parseSwf(movieUrl, movieParams, objectParams);
 
   if (isOverlay) {
-    document.getElementById('overlay').className = 'enabled';
     var fallbackDiv = document.getElementById('fallback');
+    fallbackDiv.className = 'enabled';
     fallbackDiv.addEventListener('click', function(e) {
       fallback();
       e.preventDefault();
     });
-    var reportDiv = document.getElementById('report');
-    reportDiv.addEventListener('click', function(e) {
-      reportIssue();
-      e.preventDefault();
-    });
     var fallbackMenu = document.getElementById('fallbackMenu');
     fallbackMenu.removeAttribute('hidden');
     fallbackMenu.addEventListener('click', fallback);
   }
   var showURLMenu = document.getElementById('showURLMenu');
   showURLMenu.addEventListener('click', showURL);
   var inspectorMenu = document.getElementById('inspectorMenu');
   inspectorMenu.addEventListener('click', showInInspector);
-  var reportMenu = document.getElementById('reportMenu');
-  reportMenu.addEventListener('click', reportIssue);
 
   document.getElementById('copyProfileMenu').addEventListener('click', copyProfile);
 }
 
 function showURL() {
-  window.prompt("Copy to clipboard", movieUrl);
+  var flashParams = JSON.parse(FirefoxCom.requestSync('getPluginParams', null));
+  window.prompt("Copy to clipboard", flashParams.url);
 }
 
 function showInInspector() {
   var base = "http://www.areweflashyet.com/shumway/examples/inspector/inspector.html?rfile=";
   var params = '';
   for (var k in movieParams) {
     params += '&' + k + '=' + encodeURIComponent(movieParams[k]);
   }
   window.open(base + encodeURIComponent(movieUrl) + params);
 }
 
-function reportIssue() {
-  var duplicatesMap = Object.create(null);
-  var prunedExceptions = [];
-  avm2.exceptions.forEach(function(e) {
-    var ident = e.source + e.message + e.stack;
-    var entry = duplicatesMap[ident];
-    if (!entry) {
-      entry = duplicatesMap[ident] = {
-        source: e.source,
-        message: e.message,
-        stack: e.stack,
-        count: 0
-      };
-      prunedExceptions.push(entry);
-    }
-    entry.count++;
-  });
-  FirefoxCom.requestSync('reportIssue', JSON.stringify(prunedExceptions));
-}
-
 function copyProfile() {
   function toArray(v) {
     var array = [];
     for (var i = 0; i < v.length; i++) {
       array.push(v[i]);
     }
     return array;
   }
@@ -257,22 +231,16 @@ var FileLoadingService = {
   }
 };
 
 function parseSwf(url, movieParams, objectParams) {
   var compilerSettings = JSON.parse(
     FirefoxCom.requestSync('getCompilerSettings', null));
   enableVerifier.value = compilerSettings.verifier;
 
-  // init misc preferences
-  turboMode.value = FirefoxCom.requestSync('getBoolPref', {pref: 'shumway.turboMode', def: false});
-  hud.value = FirefoxCom.requestSync('getBoolPref', {pref: 'shumway.hud', def: false});
-  forceHidpi.value = FirefoxCom.requestSync('getBoolPref', {pref: 'shumway.force_hidpi', def: false});
-  dummyAnimation.value = FirefoxCom.requestSync('getBoolPref', {pref: 'shumway.dummyMode', def: false});
-
   console.log("Compiler settings: " + JSON.stringify(compilerSettings));
   console.log("Parsing " + url + "...");
   function loaded() {
     FirefoxCom.request('endActivation', null);
   }
 
   createAVM2(builtinPath, playerGlobalPath, avm1Path,
     compilerSettings.sysCompiler ? EXECUTION_MODE.COMPILE : EXECUTION_MODE.INTERPRET,
--- a/browser/extensions/shumway/content/web/viewer.html
+++ b/browser/extensions/shumway/content/web/viewer.html
@@ -33,75 +33,59 @@ limitations under the License.
 
       #viewer {
         position:fixed !important;
         left:0;top:0;bottom:0;right:0;
         overflow: hidden;
         line-height: 0;
       }
 
-      #overlay {
+      #fallback {
         display: none;
       }
 
-      #overlay.enabled {
+      #fallback.enabled {
         display: block;
         position:fixed;
-        bottom: 0;
-        right: 0;
-      }
-
-      #report, #fallback {
-        float: right;
-        width: 70px; height: 16px;
-        padding: 8px 4px 4px;
         color: white;
+        right: 0px; bottom: 0px; width: 70px; height: 16px;
+        padding: 4px;
+        padding-top: 8px;
         background-color: rgba(0, 0, 0, 0.62);
         font: bold 10px sans-serif;
         text-align: center;
         text-decoration: none;
       }
-      #report {
-        display: none;
-        width: 100px;
-      }
-      #overlay:hover #report {
-        display: block;
-      }
 
       #fallback .icon {
         display: none;
         color: white;
       }
 
-      #fallback:hover .icon {
+      #fallback.enabled:hover .icon {
         display: inline-block;
       }
 
-      #report:hover, #fallback:hover {
-        background-color: black;
+      #fallback:hover {
+        background-color: rgb(0, 0, 0);
       }
 
       @media screen and (max-width: 100px), screen and (max-height: 40px) {
-        body.started #overlay {
+        body.started #fallback {
           display: none;
         }
       }
     </style>
   </head>
 
   <body contextmenu="shumwayMenu">
     <div id="viewer"></div>
     <section>
-      <div id="overlay">
-        <a id="fallback" href="#">Shumway <span class="icon">&times;</span></a>
-        <a id="report" href="#">Report Problems</a>
-      </div>
+      <a id="fallback" href="#">Shumway <span class="icon">&times;</span></a>
       <menu type="context" id="shumwayMenu">
         <menuitem label="Show URL" id="showURLMenu"></menuitem>
         <menuitem label="Copy Profile" id="copyProfileMenu"></menuitem>
         <menuitem label="Open in Inspector" id="inspectorMenu"></menuitem>
-        <menuitem label="Report Problems" id="reportMenu"></menuitem>
         <menuitem label="Fallback to Flash" id="fallbackMenu" hidden></menuitem>
       </menu>
     </section>
   </body>
 </html>