From 60ffa264eec279cc9f6700703fb848fa71d38fd2 Mon Sep 17 00:00:00 2001 From: Tobias Schneider Date: Wed, 17 Oct 2012 16:48:29 +0200 Subject: [PATCH 001/210] Apply style guide fixes, cleanup code. --- src/flash/display/DisplayObject.js | 238 ++++++++++---------- src/flash/display/DisplayObjectContainer.js | 81 +++---- src/flash/display/Graphics.js | 24 +- src/flash/display/InteractiveObject.js | 7 +- src/flash/display/Loader.js | 86 +++---- src/flash/display/MovieClip.js | 149 ++++++------ src/flash/display/Sprite.js | 13 +- src/flash/display/Stage.js | 45 ++-- src/flash/events/Event.js | 19 +- src/flash/events/EventDispatcher.js | 1 - src/flash/geom/Transform.js | 49 ++-- src/swf/embed.js | 2 +- src/swf/renderer.js | 65 +----- src/swf/swf.js | 128 +++++------ 14 files changed, 426 insertions(+), 481 deletions(-) diff --git a/src/flash/display/DisplayObject.js b/src/flash/display/DisplayObject.js index a76c9366d..af77ff9b4 100644 --- a/src/flash/display/DisplayObject.js +++ b/src/flash/display/DisplayObject.js @@ -1,19 +1,19 @@ const DisplayObjectDefinition = (function () { - var BLEND_MODE_ADD = 'add'; - var BLEND_MODE_ALPHA = 'alpha'; - var BLEND_MODE_DARKEN = 'darken'; - var BLEND_MODE_DIFFERENCE = 'difference'; - var BLEND_MODE_ERASE = 'erase'; - var BLEND_MODE_HARDLIGHT = 'hardlight'; - var BLEND_MODE_INVERT = 'invert'; - var BLEND_MODE_LAYER = 'layer'; - var BLEND_MODE_LIGHTEN = 'lighten'; - var BLEND_MODE_MULTIPLY = 'multiply'; - var BLEND_MODE_NORMAL = 'normal'; - var BLEND_MODE_OVERLAY = 'overlay'; - var BLEND_MODE_SCREEN = 'screen'; - var BLEND_MODE_SHADER = 'shader'; - var BLEND_MODE_SUBTRACT = 'subtract'; + const BLEND_MODE_ADD = 'add'; + const BLEND_MODE_ALPHA = 'alpha'; + const BLEND_MODE_DARKEN = 'darken'; + const BLEND_MODE_DIFFERENCE = 'difference'; + const BLEND_MODE_ERASE = 'erase'; + const BLEND_MODE_HARDLIGHT = 'hardlight'; + const BLEND_MODE_INVERT = 'invert'; + const BLEND_MODE_LAYER = 'layer'; + const BLEND_MODE_LIGHTEN = 'lighten'; + const BLEND_MODE_MULTIPLY = 'multiply'; + const BLEND_MODE_NORMAL = 'normal'; + const BLEND_MODE_OVERLAY = 'overlay'; + const BLEND_MODE_SCREEN = 'screen'; + const BLEND_MODE_SHADER = 'shader'; + const BLEND_MODE_SUBTRACT = 'subtract'; var def = { __class__: 'flash.display.DisplayObject', @@ -24,6 +24,7 @@ const DisplayObjectDefinition = (function () { this._cacheAsBitmap = false; this._control = document.createElement('div'); this._bbox = null; + this._currentTransform = null; this._cxform = null; this._graphics = null; this._loaderInfo = null; @@ -42,12 +43,50 @@ const DisplayObjectDefinition = (function () { this._visible = true; this._x = 0; this._y = 0; - this._updateTransformMatrix(); + + this._updateCurrentTransform(); var s = this.symbol; - if (s) { + if (s) this._bbox = s.bbox || null; - } + }, + + _applyCurrentTransform: function (point) { + var m = this._currentTransform; + var x = point.x; + var y = point.y; + point.x = m.a * x + m.c * y + m.tx; + point.y = m.d * y + m.b * x + m.ty; + + if (this._parent !== this._stage) + this._parent._applyCurrentTransform(point); + }, + _updateCurrentTransform: function () { + var rotation = this._rotation / 180 * Math.PI; + var scaleX = this._scaleX; + var scaleY = this._scaleY; + var u = Math.cos(rotation); + var v = Math.sin(rotation); + + this._currentTransform = { + a: u * scaleX, + b: v * scaleX, + c: -v * scaleY, + d: u * scaleY, + tx: this._x, + ty: this._y + }; + }, + _applyCurrentInverseTransform: function (point) { + if (this._parent !== this._stage) + this._parent._applyCurrentInverseTransform(point); + + var m = this._currentTransform; + var x = point.x - m.tx; + var y = point.y - m.ty; + var d = 1 / (m.a * m.d - m.b * m.c); + point.x = (m.d * x - m.c * y) * d; + point.y = (m.a * y - m.b * x) * d; }, get accessibilityProperties() { @@ -81,86 +120,6 @@ const DisplayObjectDefinition = (function () { set filters(val) { notImplemented(); }, - getBounds: function (targetCoordSpace) { - var bbox = this._bbox; - - if (!bbox) - return new flash.geom.Rectangle; - - var m = this._currentTransformMatrix; - - var x1 = m.a * bbox.left + m.c * bbox.top; - var y1 = m.d * bbox.top + m.b * bbox.left; - var x2 = m.a * bbox.right + m.c * bbox.top; - var y2 = m.d * bbox.top + m.b * bbox.right; - var x3 = m.a * bbox.right + m.c * bbox.bottom; - var y3 = m.d * bbox.bottom + m.b * bbox.right; - var x4 = m.a * bbox.left + m.c * bbox.bottom; - var y4 = m.d * bbox.bottom + m.b * bbox.left; - - var xMin = Math.min(x1, x2, x3, x4); - var xMax = Math.max(x1, x2, x3, x4); - var yMin = Math.min(y1, y2, y3, y4); - var yMax = Math.max(y1, y2, y3, y4); - - return new flash.geom.Rectangle( - xMin + m.tx, - yMin + m.ty, - (xMax - xMin), - (yMax - yMin) - ); - }, - _updateTransformMatrix: function () { - var rotation = this._rotation / 180 * Math.PI; - var scaleX = this._scaleX; - var scaleY = this._scaleY; - var u = Math.cos(rotation); - var v = Math.sin(rotation); - - this._currentTransformMatrix = { - a: u * scaleX, - b: v * scaleX, - c: -v * scaleY, - d: u * scaleY, - tx: this._x, - ty: this._y - }; - }, - _applyCurrentTransform: function (point) { - var m = this._currentTransformMatrix; - var x = point.x; - var y = point.y; - - point.x = m.a * x + m.c * y + m.tx; - point.y = m.d * y + m.b * x + m.ty; - - if (this._parent !== this._stage) { - this._parent._applyCurrentTransform(point); - } - }, - _applyCurrentInverseTransform: function (point) { - if (this._parent !== this._stage) { - this._parent._applyCurrentInverseTransform(point); - } - - var m = this._currentTransformMatrix; - - var x = point.x - m.tx; - var y = point.y - m.ty; - var d = 1 / (m.a * m.d - m.b * m.c); - - point.x = (m.d * x - m.c * y) * d; - point.y = (m.a * y - m.b * x) * d; - }, - getRect: function (targetCoordSpace) { - notImplemented(); - }, - globalToLocal: function (pt) { - var result = new flash.geom.Point(pt.x, pt.y); - this._applyCurrentInverseTransform(result); - debugger; - return result; - }, get height() { var bounds = this.getBounds(); return bounds.height; @@ -168,23 +127,9 @@ const DisplayObjectDefinition = (function () { set height(val) { notImplemented(); }, - hitTestObject: function (obj) { - notImplemented(); - }, - hitTestPoint: function (x, y, shapeFlag) { - notImplemented(); - }, - hitTest: function _hitTest(use_xy, x, y, useShape, hitTestObject) { - return false; //notImplemented(); - }, get loaderInfo() { return this._loaderInfo || (this._parent ? this._parent.loaderInfo : null); }, - localToGlobal: function (pt) { - var result = new flash.geom.Point(pt.x, pt.y); - this._applyCurrentTransform(result); - return result; - }, get mask() { return null; }, @@ -220,7 +165,7 @@ const DisplayObjectDefinition = (function () { }, set rotation(val) { this._rotation = val; - this._updateTransformMatrix(); + this._updateCurrentTransform(); this._slave = false; }, get stage() { @@ -231,7 +176,7 @@ const DisplayObjectDefinition = (function () { }, set scaleX(val) { this._scaleX = val; - this._updateTransformMatrix(); + this._updateCurrentTransform(); this._slave = false; }, get scaleY() { @@ -239,7 +184,7 @@ const DisplayObjectDefinition = (function () { }, set scaleY(val) { this._scaleY = val; - this._updateTransformMatrix(); + this._updateCurrentTransform(); this._slave = false; }, get scale9Grid() { @@ -261,7 +206,7 @@ const DisplayObjectDefinition = (function () { var transform = this._transform; transform.colorTransform = val.colorTransform; transform.matrix = val.matrix; - this._currentTransformMatrix = val.matrix; + this._currentTransform = val.matrix; this._slave = false; }, get visible() { @@ -283,7 +228,7 @@ const DisplayObjectDefinition = (function () { }, set x(val) { this._x = val; - this._updateTransformMatrix(); + this._updateCurrentTransform(); this._slave = false; }, get y() { @@ -291,8 +236,65 @@ const DisplayObjectDefinition = (function () { }, set y(val) { this._y = val; - this._updateTransformMatrix(); + this._updateCurrentTransform(); this._slave = false; + }, + + getBounds: function (targetCoordSpace) { + var bbox = this._bbox; + + if (!bbox) + return new flash.geom.Rectangle; + + var m = this._currentTransform; + var a = m.a; + var b = m.b; + var c = m.c; + var d = m.d; + + var x1 = a * bbox.left + c * bbox.top; + var y1 = d * bbox.top + b * bbox.left; + var x2 = a * bbox.right + c * bbox.top; + var y2 = d * bbox.top + b * bbox.right; + var x3 = a * bbox.right + c * bbox.bottom; + var y3 = d * bbox.bottom + b * bbox.right; + var x4 = a * bbox.left + c * bbox.bottom; + var y4 = d * bbox.bottom + b * bbox.left; + + var xMin = Math.min(x1, x2, x3, x4); + var xMax = Math.max(x1, x2, x3, x4); + var yMin = Math.min(y1, y2, y3, y4); + var yMax = Math.max(y1, y2, y3, y4); + + return new flash.geom.Rectangle( + xMin + m.tx, + yMin + m.ty, + (xMax - xMin), + (yMax - yMin) + ); + }, + getRect: function (targetCoordSpace) { + notImplemented(); + }, + globalToLocal: function (pt) { + var result = new flash.geom.Point(pt.x, pt.y); + this._applyCurrentInverseTransform(result); + debugger; + return result; + }, + hitTestObject: function (obj) { + notImplemented(); + }, + hitTestPoint: function (x, y, shapeFlag) { + notImplemented(); + }, + hitTest: function (use_xy, x, y, useShape, hitTestObject) { + return false; //notImplemented(); + }, + localToGlobal: function (pt) { + var result = new flash.geom.Point(pt.x, pt.y); + this._applyCurrentTransform(result); + return result; } }; diff --git a/src/flash/display/DisplayObjectContainer.js b/src/flash/display/DisplayObjectContainer.js index 81e7f8f83..c27096252 100644 --- a/src/flash/display/DisplayObjectContainer.js +++ b/src/flash/display/DisplayObjectContainer.js @@ -4,6 +4,47 @@ const DisplayObjectContainerDefinition = (function () { this._children = []; }, + get _bbox() { + var children = this._children; + var numChildren = children.length; + + if (!numChildren) { + return { + left: 0, + top: 0, + right: 0, + bottom: 0 + } + } + + var xMin = Number.MAX_VALUE; + var xMax = 0; + var yMin = Number.MAX_VALUE; + var yMax = 0; + + for (var i = 0; i < numChildren; i++) { + var child = children[i]; + var b = child.getBounds(); + + var x1 = b.x; + var y1 = b.y; + var x2 = b.x + b.width; + var y2 = b.y + b.height; + + xMin = Math.min(xMin, x1, x2); + xMax = Math.max(xMax, x1, x2); + yMin = Math.min(yMin, y1, y2); + yMax = Math.max(yMax, y1, y2); + } + + return { + left: xMin, + top: yMin, + right: xMax, + bottom: yMax + }; + }, + get mouseChildren() { return true; }, @@ -152,46 +193,6 @@ const DisplayObjectContainerDefinition = (function () { children[index2] = child1; child1._owned = false; child2._owned = false; - }, - get _bbox() { - var children = this._children; - var numChildren = children.length; - - if (!numChildren) { - return { - left: 0, - top: 0, - right: 0, - bottom: 0 - } - } - - var xMin = Number.MAX_VALUE; - var xMax = 0; - var yMin = Number.MAX_VALUE; - var yMax = 0; - - for (var i = 0; i < numChildren; i++) { - var child = children[i]; - var b = child.getBounds(); - - var x1 = b.x; - var y1 = b.y; - var x2 = b.x + b.width; - var y2 = b.y + b.height; - - xMin = Math.min(xMin, x1, x2); - xMax = Math.max(xMax, x1, x2); - yMin = Math.min(yMin, y1, y2); - yMax = Math.max(yMax, y1, y2); - } - - return { - left: xMin, - top: yMin, - right: xMax, - bottom: yMax - }; } }; diff --git a/src/flash/display/Graphics.js b/src/flash/display/Graphics.js index e3c2993f3..cb8f78b11 100644 --- a/src/flash/display/Graphics.js +++ b/src/flash/display/Graphics.js @@ -30,6 +30,18 @@ const GraphicsDefinition = (function () { this._subpaths = []; }, + get _currentPath() { + var path = new Kanvas.Path; + path.drawingStyles = this._drawingStyles; + path.fillStyle = this._fillStyle; + path.fillTransform = this._fillTransform; + path.strokeStyle = this._strokeStyle; + this._subpaths.push(path); + // Cache as an own property. + Object.defineProperty(this, '_currentPath', describeProperty(path)); + return path; + }, + beginFill: function (color, alpha) { if (alpha === undefined) alpha = 1; @@ -268,18 +280,6 @@ const GraphicsDefinition = (function () { }, lineTo: function (x, y) { this._currentPath.lineTo(x, y); - }, - - get _currentPath() { - var path = new Kanvas.Path; - path.drawingStyles = this._drawingStyles; - path.fillStyle = this._fillStyle; - path.fillTransform = this._fillTransform; - path.strokeStyle = this._strokeStyle; - this._subpaths.push(path); - // Cache as an own property. - Object.defineProperty(this, '_currentPath', describeProperty(path)); - return path; } }; diff --git a/src/flash/display/InteractiveObject.js b/src/flash/display/InteractiveObject.js index 860555e84..4aa676dfb 100644 --- a/src/flash/display/InteractiveObject.js +++ b/src/flash/display/InteractiveObject.js @@ -40,9 +40,6 @@ const InteractiveObjectDefinition = (function () { set needsSoftKeyboard(val) { notImplemented(); }, - requestSoftKeyboard: function () { - notImplemented(); - }, get softKeyboardInputAreaOfInterest() { return null; }, @@ -57,6 +54,10 @@ const InteractiveObjectDefinition = (function () { }, get tabIndex() { return -1; + }, + + requestSoftKeyboard: function () { + notImplemented(); } }; diff --git a/src/flash/display/Loader.js b/src/flash/display/Loader.js index 2dfaeb82e..d0bc9b364 100644 --- a/src/flash/display/Loader.js +++ b/src/flash/display/Loader.js @@ -33,7 +33,7 @@ const LoaderDefinition = (function () { var commitData; if (loader) { commitData = function (data) { - return loader.commitData(data); + return loader._commitData(data); }; } else { commitData = function (data) { @@ -143,7 +143,6 @@ const LoaderDefinition = (function () { symbols[swfTag.id] = symbol; commitData(symbol); } - function parseBytes(bytes) { var depths = { }; var frame = { type: 'frame' }; @@ -284,28 +283,14 @@ const LoaderDefinition = (function () { this._timeline = []; }, - get contentLoaderInfo() { - // XXX: Why is this lazily initialized? - var loaderInfo = this._contentLoaderInfo; - if (!loaderInfo) { - loaderInfo = new flash.display.LoaderInfo; - loaderInfo._loader = this; - this._contentLoaderInfo = loaderInfo; - } - return loaderInfo; - }, - - close: function () { - notImplemented(); - }, - commitData: function (data) { + _commitData: function (data) { var loaderInfo = this.contentLoaderInfo; loaderInfo.dispatchEvent(new flash.events.Event("progress")); switch (data.command) { case 'init': - this.init(data.result); + this._init(data.result); break; case 'complete': loaderInfo.dispatchEvent(new flash.events.Event("complete")); @@ -315,13 +300,13 @@ const LoaderDefinition = (function () { break; default: if (data.id) - this.commitSymbol(data); + this._commitSymbol(data); else if (data.type === 'frame') - this.commitFrame(data); + this._commitFrame(data); break; } }, - commitFrame: function (frame) { + _commitFrame: function (frame) { var abcBlocks = frame.abcBlocks; var depths = frame.depths; var exports = frame.exports; @@ -418,7 +403,7 @@ const LoaderDefinition = (function () { loaderInfo.dispatchEvent(new flash.events.Event('init')); }); }, - commitSymbol: function (symbol) { + _commitSymbol: function (symbol) { var dependencies = symbol.require; var dictionary = this._dictionary; var promiseQueue = []; @@ -558,21 +543,7 @@ const LoaderDefinition = (function () { symbolPromise.resolve(symbolInfo); }); }, - getSymbolInfoByName: function (className) { - var dictionary = this._dictionary; - for (var id in dictionary) { - var promise = dictionary[id]; - var symbolInfo = promise.value; - if (symbolInfo && symbolInfo.className === className) - return symbolInfo; - } - return null; - }, - getSymbolInfoById: function (id) { - var promise = this._dictionary[id]; - return promise ? promise.value : null; - }, - init: function (info) { + _init: function (info) { var loader = this; var loaderInfo = loader.contentLoaderInfo; @@ -599,30 +570,21 @@ const LoaderDefinition = (function () { loader._vmPromise = vmPromise; loader._isAvm2Enabled = info.fileAttributes.doAbc; - this.setup(); + this._setup(); }, - load: function (request, context) { - this.loadFrom(request.url); - }, - loadBytes: function (bytes, context) { - if (!bytes.length) - throw ArgumentError(); - - this.loadFrom(bytes); - }, - loadFrom: function (input, context) { + _loadFrom: function (input, context) { if (typeof window !== 'undefined' && WORKERS_ENABLED) { var loader = this; var worker = new Worker(SHUMWAY_ROOT + LOADER_PATH); worker.onmessage = function (evt) { - loader.commitData(evt.data); + loader._commitData(evt.data); }; worker.postMessage(input); } else { loadFromWorker(this, input, context); } }, - setup: function () { + _setup: function () { var loader = this; var stage = loader._stage; @@ -637,6 +599,30 @@ const LoaderDefinition = (function () { loader._vmPromise.resolve(); } }, + + get contentLoaderInfo() { + // XXX: Why is this lazily initialized? + var loaderInfo = this._contentLoaderInfo; + if (!loaderInfo) { + loaderInfo = new flash.display.LoaderInfo; + loaderInfo._loader = this; + this._contentLoaderInfo = loaderInfo; + } + return loaderInfo; + }, + + close: function () { + notImplemented(); + }, + load: function (request, context) { + this._loadFrom(request.url); + }, + loadBytes: function (bytes, context) { + if (!bytes.length) + throw ArgumentError(); + + this._loadFrom(bytes); + }, unload: function () { notImplemented(); }, diff --git a/src/flash/display/MovieClip.js b/src/flash/display/MovieClip.js index 171691194..f801fc8df 100644 --- a/src/flash/display/MovieClip.js +++ b/src/flash/display/MovieClip.js @@ -27,61 +27,22 @@ const MovieClipDefinition = (function () { } }, - addFrameScript: function () { - // arguments are pairs of frameIndex and script/function - // frameIndex is in range 0..totalFrames-1 - 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]; - var scripts = frameScripts[frameNum]; - if (scripts) - scripts.push(fn); - else - frameScripts[frameNum] = [fn]; - } - }, - callFrame: function (frameNum) { + _callFrame: function (frameNum) { if (frameNum in this._frameScripts) { var scripts = this._frameScripts[frameNum]; for (var i = 0, n = scripts.length; i < n; i++) scripts[i].call(this); } }, - get currentFrame() { - return this._currentFrame; - }, - get currentFrameLabel() { - return this._currentFrameLabel; - }, - get currentLabel() { - return this._currentLabel; - }, - get currentLabels() { - return this._currentScene.labels; - }, - get currentScene() { - return this._currentScene; - }, - get enabled() { - return this._enabled; - }, - set enabled(val) { - this._enabled = val; - }, - get framesLoaded() { - return this._framesLoaded; - }, - gotoFrame: function (frameNum, scene) { + _gotoFrame: function (frameNum, scene) { if (frameNum > this._totalFrames) frameNum = 1; if (frameNum > this.framesLoaded) frameNum = this.framesLoaded; - if (frameNum === this._currentFrame) { + if (frameNum === this._currentFrame) return; - } var children = this._children; var depthMap = this._depthMap; @@ -111,7 +72,7 @@ const MovieClipDefinition = (function () { if (cmd.symbolId) { var index = 0; - var symbolInfo = loader.getSymbolInfoById(cmd.symbolId); + var symbolInfo = loader._symbols[cmd.symbolId]; var symbolClass = avm2.systemDomain.getClass(symbolInfo.className); var instance = symbolClass.createAsSymbol(symbolInfo.props); var replace = 0; @@ -142,9 +103,8 @@ const MovieClipDefinition = (function () { // If we bound the instance to a name, set it. // // XXX: I think this always has to be a trait. - if (cmd.name) { + if (cmd.name) this[Multiname.getPublicQualifiedName(cmd.name)] = instance; - } // Call the constructor now that we've made the symbol instance, // instantiated all its children, and set the display list-specific @@ -164,46 +124,100 @@ const MovieClipDefinition = (function () { if (cxform) target._cxform = cxform; if (matrix) { - target._rotation = Math.atan2(matrix.b, matrix.a) * 180 / Math.PI; - var sx = Math.sqrt(matrix.a * matrix.a + matrix.b * matrix.b); - target._scaleX = matrix.a > 0 ? sx : -sx; - var sy = Math.sqrt(matrix.d * matrix.d + matrix.c * matrix.c); - target._scaleY = matrix.d > 0 ? sy : -sy; - target._x = matrix.tx / 20; - target._y = matrix.ty / 20; - target._currentTransformMatrix = { - a: matrix.a, - b: matrix.b, - c: matrix.c, - d: matrix.d, - tx: target._x, - ty: target._y + var a = matrix.a; + var b = matrix.b; + var c = matrix.c; + var d = matrix.d; + + target._rotation = Math.atan2(b, a) * 180 / Math.PI; + var sx = Math.sqrt(a * a + b * b); + target._scaleX = a > 0 ? sx : -sx; + var sy = Math.sqrt(d * d + c * c); + target._scaleY = d > 0 ? sy : -sy; + var x = target._x = matrix.tx / 20; + var y = target._y = matrix.ty / 20; + + target._currentTransform = { + a: a, + b: b, + c: c, + d: d, + tx: x, + ty: y }; } } } this._currentFrame = frameNum; - this._scriptExecutionPending = true; + }, + + get currentFrame() { + return this._currentFrame; + }, + get currentFrameLabel() { + return this._currentFrameLabel; + }, + get currentLabel() { + return this._currentLabel; + }, + get currentLabels() { + return this._currentScene.labels; + }, + get currentScene() { + return this._currentScene; + }, + get enabled() { + return this._enabled; + }, + set enabled(val) { + this._enabled = val; + }, + get framesLoaded() { + return this._framesLoaded; + }, + get totalFrames() { + return this._totalFrames; + }, + get trackAsMenu() { + return false; + }, + set trackAsMenu(val) { + notImplemented(); + }, + + addFrameScript: function () { + // arguments are pairs of frameIndex and script/function + // frameIndex is in range 0..totalFrames-1 + 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]; + var scripts = frameScripts[frameNum]; + if (scripts) + scripts.push(fn); + else + frameScripts[frameNum] = [fn]; + } }, gotoAndPlay: function (frame, scene) { this.play(); if (isNaN(frame)) this.gotoLabel(frame); else - this.gotoFrame(frame); + this._gotoFrame(frame); }, gotoAndStop: function (frame, scene) { this.stop(); if (isNaN(frame)) this.gotoLabel(frame); else - this.gotoFrame(frame); + this._gotoFrame(frame); }, gotoLabel: function (labelName) { var frameLabel = this._frameLabels[labelName]; if (frameLabel) - this.gotoFrame(frameLabel.frame); + this._gotoFrame(frameLabel.frame); }, isPlaying: function () { return this._isPlaying; @@ -225,15 +239,6 @@ const MovieClipDefinition = (function () { }, stop: function () { this._isPlaying = false; - }, - get totalFrames() { - return this._totalFrames; - }, - get trackAsMenu() { - return false; - }, - set trackAsMenu(val) { - notImplemented(); } }; diff --git a/src/flash/display/Sprite.js b/src/flash/display/Sprite.js index 0c5dc0e62..f22b43c5e 100644 --- a/src/flash/display/Sprite.js +++ b/src/flash/display/Sprite.js @@ -32,6 +32,13 @@ const SpriteDefinition = (function () { set soundTransform(val) { notImplemented(); }, + get useHandCursor() { + return true; + }, + set useHandCursor(val) { + notImplemented(); + }, + startDrag: function (lockCenter, bounds) { notImplemented(); }, @@ -43,12 +50,6 @@ const SpriteDefinition = (function () { }, stopTouchDrag: function (touchPointID) { notImplemented(); - }, - get useHandCursor() { - return true; - }, - set useHandCursor(val) { - notImplemented(); } }; diff --git a/src/flash/display/Stage.js b/src/flash/display/Stage.js index 9b631b877..0f0e9cfd3 100644 --- a/src/flash/display/Stage.js +++ b/src/flash/display/Stage.js @@ -1,30 +1,30 @@ const StageDefinition = (function () { - var COLOR_CORRECTION_DEFAULT = 'default'; - var COLOR_CORRECTION_OFF = 'on'; - var COLOR_CORRECTION_ON = 'off'; + const COLOR_CORRECTION_DEFAULT = 'default'; + const COLOR_CORRECTION_OFF = 'on'; + const COLOR_CORRECTION_ON = 'off'; - var COLOR_CORRECTION_DEFAULT_OFF = 'defaultOff'; - var COLOR_CORRECTION_DEFAULT_ON = 'defaultOn'; - var COLOR_CORRECTION_UNSUPPORTED = 'unsuported'; + const COLOR_CORRECTION_DEFAULT_OFF = 'defaultOff'; + const COLOR_CORRECTION_DEFAULT_ON = 'defaultOn'; + const COLOR_CORRECTION_UNSUPPORTED = 'unsuported'; - var STAGE_ALIGN_BOTTOM = 'B'; - var STAGE_ALIGN_BOTTOM_LEFT = 'BL'; - var STAGE_ALIGN_BOTTOM_RIGHT = 'BR'; - var STAGE_ALIGN_LEFT = 'L'; - var STAGE_ALIGN_RIGHT = 'R'; - var STAGE_ALIGN_TOP = 'T'; - var STAGE_ALIGN_TOP_LEFT = 'TL'; - var STAGE_ALIGN_TOP_RIGHT = 'TR'; + const STAGE_ALIGN_BOTTOM = 'B'; + const STAGE_ALIGN_BOTTOM_LEFT = 'BL'; + const STAGE_ALIGN_BOTTOM_RIGHT = 'BR'; + const STAGE_ALIGN_LEFT = 'L'; + const STAGE_ALIGN_RIGHT = 'R'; + const STAGE_ALIGN_TOP = 'T'; + const STAGE_ALIGN_TOP_LEFT = 'TL'; + const STAGE_ALIGN_TOP_RIGHT = 'TR'; - var STAGE_SCALE_MODE_EXACT_FIT = 'exactFit'; - var STAGE_SCALE_MODE_NO_BORDER = 'noBorder'; - var STAGE_SCALE_MODE_NO_SCALE = 'noScale'; - var STAGE_SCALE_MODE_SHOW_ALL = 'showAll'; + const STAGE_SCALE_MODE_EXACT_FIT = 'exactFit'; + const STAGE_SCALE_MODE_NO_BORDER = 'noBorder'; + const STAGE_SCALE_MODE_NO_SCALE = 'noScale'; + const STAGE_SCALE_MODE_SHOW_ALL = 'showAll'; - var STAGE_QUALITY_BEST = 'best'; - var STAGE_QUALITY_HIGH = 'high'; - var STAGE_QUALITY_LOW = 'low'; - var STAGE_QUALITY_MEDIUM = 'medium'; + const STAGE_QUALITY_BEST = 'best'; + const STAGE_QUALITY_HIGH = 'high'; + const STAGE_QUALITY_LOW = 'low'; + const STAGE_QUALITY_MEDIUM = 'medium'; var def = { __class__: 'flash.display.Stage', @@ -116,6 +116,7 @@ const StageDefinition = (function () { get wmodeGPU() { return false; }, + invalidate: function () { notImplemented(); }, diff --git a/src/flash/events/Event.js b/src/flash/events/Event.js index b6944e543..83f30c0dc 100644 --- a/src/flash/events/Event.js +++ b/src/flash/events/Event.js @@ -13,17 +13,21 @@ const EventDefinition = (function () { this._target = null; }, - ctor: function (type, bubbles, cancelable) { - this.type = type; - this.bubbles = !!bubbles; - this.cancelable = !!cancelable; - }, get currentTarget() { return this._currentTarget; }, get eventPhase() { return this._eventPhase; }, + get target() { + return this._target; + }, + + ctor: function (type, bubbles, cancelable) { + this.type = type; + this.bubbles = !!bubbles; + this.cancelable = !!cancelable; + }, isDefaultPrevented: function () { return this._isDefaultPrevented; }, @@ -35,10 +39,7 @@ const EventDefinition = (function () { }, stopPropagation: function () { notImplemented(); - }, - get target() { - return this._target; - }, + } }; const desc = Object.getOwnPropertyDescriptor; diff --git a/src/flash/events/EventDispatcher.js b/src/flash/events/EventDispatcher.js index 08a5198cb..10b5a0854 100644 --- a/src/flash/events/EventDispatcher.js +++ b/src/flash/events/EventDispatcher.js @@ -13,7 +13,6 @@ const EventDispatcherDefinition = (function () { ctor: function (target) { this._target = target; }, - addEventListener: function (type, listener, useCapture, prio, useWeakReference) { if (typeof listener !== 'function') throw ArgumentError(); diff --git a/src/flash/geom/Transform.js b/src/flash/geom/Transform.js index e58bbbd11..ceb8e6cf4 100644 --- a/src/flash/geom/Transform.js +++ b/src/flash/geom/Transform.js @@ -2,11 +2,6 @@ const TransformDefinition = (function () { var def = { __class__: 'flash.geom.Transform', - ctor: function (target) { - this._target = target; - - target._transform = this; - }, get colorTransform() { var cxform = this._target._cxform; if (cxform) { @@ -51,30 +46,44 @@ const TransformDefinition = (function () { return m; }, get matrix() { - var target = this._target; - var m = new flash.geom.Matrix; - m.createBox( - target._scaleX, - target._scaleY, - target._rotation * Math.PI / 180, - target._x, - target._y - ); - return m; + var m = this._target._currentTransform; + return new flash.geom.Matrix(m.a, m.b, m.c, m.d, m.tx, m.ty); }, set matrix(val) { var MatrixClass = avm2.systemDomain.getClass("flash.geom.Matrix"); if (!MatrixClass.isInstanceOf(val)) throw TypeError(); + var a = val.a; + var b = val.b; + var c = val.c; + var d = val.d; + var tx = val.tx; + var ty = val.ty; + var target = this._target; - target._rotation = Math.atan2(val.b, val.a) * 180 / Math.PI; - var sx = Math.sqrt(val.a * val.a + val.b * val.b); - target._scaleX = val.a > 0 ? sx : -sx; - var sy = Math.sqrt(val.d * val.d + val.c * val.c); - target._scaleY = val.d > 0 ? sy : -sy; + target._rotation = Math.atan2(b, a) * 180 / Math.PI; + var sx = Math.sqrt(a * a + b * b); + target._scaleX = a > 0 ? sx : -sx; + var sy = Math.sqrt(d * d + c * c); + target._scaleY = d > 0 ? sy : -sy; target._x = val.tx; target._y = val.ty; + + target._currentTransform = { + a: a, + b: b, + c: c, + d: d, + tx: tx, + ty: ty + }; + }, + + ctor: function (target) { + this._target = target; + + target._transform = this; } }; diff --git a/src/swf/embed.js b/src/swf/embed.js index de60f8419..9091c4834 100644 --- a/src/swf/embed.js +++ b/src/swf/embed.js @@ -54,5 +54,5 @@ SWF.embed = function(file, container, options) { }); } - loader.loadFrom(file); + loader._loadFrom(file); }; diff --git a/src/swf/renderer.js b/src/swf/renderer.js index 588730ca5..ce2aefada 100644 --- a/src/swf/renderer.js +++ b/src/swf/renderer.js @@ -1,58 +1,3 @@ -/* -*- mode: javascript; tab-width: 4; insert-tabs-mode: nil; indent-tabs-mode: nil -*- */ - -//function renderShadowCanvas(child) { -// var cache = child.hitTestCache; -// -// var bounds = child.getBounds(); -// var offsetX = Math.floor(bounds.x / 20); -// var offsetY = Math.floor(bounds.y / 20); -// var sizeX = Math.ceil(bounds.width / 20); -// var sizeY = Math.ceil(bounds.height / 20); -// -// var canvas = cache.canvas; -// if (!canvas) { -// cache.canvas = canvas = document.createElement('canvas'); -// cache.isPixelPainted = function(x, y) { -// x = 0 | (x - offsetX); -// y = 0 | (y - offsetY); -// if (x < 0 || y < 0 || x >= sizeX || y >= sizeY) -// return false; -// var data = cache.imageData.data; -// var result = data[(x + sizeX * y) * 4 + 3]; -// return !!result; -// }; -// } -// -// if (sizeX <= 0 || sizeY <= 0) -// return; -// -// canvas.width = sizeX; -// canvas.height = sizeY; -// -// var ctx = canvas.getContext('2d'); -// ctx.save(); -// ctx.mozFillRule = 'evenodd'; -// ctx.clearRect(0, 0, sizeX, sizeY); -// ctx.translate(-offsetX, -offsetY); -// ctx.scale(0.05, 0.05); -// -// if (child.draw) -// child.draw(ctx, child.ratio); -// else if (child.nextFrame) { -// var renderContext = { -// isHitTestRendering: true, -// beginDrawing: function() { return ctx; }, -// endDrawing: function() {} -// }; -// child.renderNextFrame(renderContext); -// } -// -// ctx.restore(); -// -// cache.ratio = child.ratio; -// cache.imageData = ctx.getImageData(0, 0, sizeX, sizeY); -//} - function renderStage(stage, ctx) { // All the visitors close over this class to do instance testing. const MovieClipClass = avm2.systemDomain.getClass("flash.display.MovieClip"); @@ -82,6 +27,7 @@ function renderStage(stage, ctx) { if (MovieClipClass.isInstanceOf(obj)) { if (obj.isPlaying()) { obj.nextFrame(); + obj._scriptExecutionPending = true; } obj.dispatchEvent(new flash.events.Event("enterFrame")); } @@ -132,7 +78,7 @@ function renderStage(stage, ctx) { // TODO move into separate visitor? if (MovieClipClass.isInstanceOf(parent) && parent._scriptExecutionPending) { - parent.callFrame(parent.currentFrame); + parent._callFrame(parent.currentFrame); parent._scriptExecutionPending = false; } }, @@ -143,10 +89,6 @@ function renderStage(stage, ctx) { visit: function (child, isContainer) { var ctx = this.ctx; ctx.save(); - //if (child.matrix && !child.$fixMatrix) - // child.matrix = create(child.matrix); - //if (child.cxform && !child.$fixCxform) - // child.cxform = create(child.cxform); var m = child._currentTransformMatrix; ctx.transform(m.a, m.b, m.c, m.d, m.tx, m.ty); @@ -198,9 +140,6 @@ function renderStage(stage, ctx) { // letting the container to restore transforms after all children are painted ctx.restore(); } - - //if (child.hitTestCache && child.hitTestCache.ratio != child.ratio) - // renderShadowCanvas(child); } }; diff --git a/src/swf/swf.js b/src/swf/swf.js index ba826c7aa..cf404baae 100644 --- a/src/swf/swf.js +++ b/src/swf/swf.js @@ -1,66 +1,66 @@ -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_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; +const SWF_TAG_CODE_CSM_TEXT_SETTINGS = 74; +const SWF_TAG_CODE_DEFINE_BINARY_DATA = 87; +const SWF_TAG_CODE_DEFINE_BITS = 6; +const SWF_TAG_CODE_DEFINE_BITS_JPEG2 = 21; +const SWF_TAG_CODE_DEFINE_BITS_JPEG3 = 35; +const SWF_TAG_CODE_DEFINE_BITS_JPEG4 = 90; +const SWF_TAG_CODE_DEFINE_BITS_LOSSLESS = 20; +const SWF_TAG_CODE_DEFINE_BITS_LOSSLESS2 = 36; +const SWF_TAG_CODE_DEFINE_BUTTON = 7; +const SWF_TAG_CODE_DEFINE_BUTTON2 = 34; +const SWF_TAG_CODE_DEFINE_BUTTON_CXFORM = 23; +const SWF_TAG_CODE_DEFINE_BUTTON_SOUND = 17; +const SWF_TAG_CODE_DEFINE_EDIT_TEXT = 37; +const SWF_TAG_CODE_DEFINE_FONT = 10; +const SWF_TAG_CODE_DEFINE_FONT2 = 48; +const SWF_TAG_CODE_DEFINE_FONT3 = 75; +const SWF_TAG_CODE_DEFINE_FONT4 = 91; +const SWF_TAG_CODE_DEFINE_FONT_ALIGN_ZONES = 73; +const SWF_TAG_CODE_DEFINE_FONT_INFO = 13; +const SWF_TAG_CODE_DEFINE_FONT_INFO2 = 62; +const SWF_TAG_CODE_DEFINE_FONT_NAME = 88; +const SWF_TAG_CODE_DEFINE_MORPH_SHAPE = 46; +const SWF_TAG_CODE_DEFINE_MORPH_SHAPE2 = 84; +const SWF_TAG_CODE_DEFINE_SCALING_GRID = 78; +const SWF_TAG_CODE_DEFINE_SCENE_AND_FRAME_LABEL_DATA = 86; +const SWF_TAG_CODE_DEFINE_SHAPE = 2; +const SWF_TAG_CODE_DEFINE_SHAPE2 = 22; +const SWF_TAG_CODE_DEFINE_SHAPE3 = 32; +const SWF_TAG_CODE_DEFINE_SHAPE4 = 83; +const SWF_TAG_CODE_DEFINE_SOUND = 14; +const SWF_TAG_CODE_DEFINE_SPRITE = 39; +const SWF_TAG_CODE_DEFINE_TEXT = 11; +const SWF_TAG_CODE_DEFINE_TEXT2 = 33; +const SWF_TAG_CODE_DEFINE_VIDEO_STREAM = 60; +const SWF_TAG_CODE_DO_ABC = 82; +const SWF_TAG_CODE_DO_ACTION = 12; +const SWF_TAG_CODE_DO_INIT_ACTION = 59; +const SWF_TAG_CODE_ENABLE_DEBUGGER = 58; +const SWF_TAG_CODE_ENABLE_DEBUGGER2 = 64; +const SWF_TAG_CODE_END = 0; +const SWF_TAG_CODE_EXPORT_ASSETS = 56; +const SWF_TAG_CODE_FILE_ATTRIBUTES = 69; +const SWF_TAG_CODE_FRAME_LABEL = 43; +const SWF_TAG_CODE_IMPORT_ASSETS = 57; +const SWF_TAG_CODE_IMPORT_ASSETS2 = 71; +const SWF_TAG_CODE_JPEG_TABLES = 8; +const SWF_TAG_CODE_METADATA = 77; +const SWF_TAG_CODE_PLACE_OBJECT = 4; +const SWF_TAG_CODE_PLACE_OBJECT2 = 26; +const SWF_TAG_CODE_PLACE_OBJECT3 = 70; +const SWF_TAG_CODE_PROTECT = 24; +const SWF_TAG_CODE_REMOVE_OBJECT = 5; +const SWF_TAG_CODE_REMOVE_OBJECT2 = 28; +const SWF_TAG_CODE_SCRIPT_LIMITS = 65; +const SWF_TAG_CODE_SET_BACKGROUND_COLOR = 9; +const SWF_TAG_CODE_SET_TAB_INDEX = 66; +const SWF_TAG_CODE_SHOW_FRAME = 1; +const SWF_TAG_CODE_SOUND_STREAM_BLOCK = 19; +const SWF_TAG_CODE_SOUND_STREAM_HEAD = 18; +const SWF_TAG_CODE_SOUND_STREAM_HEAD2 = 45; +const SWF_TAG_CODE_START_SOUND = 15; +const SWF_TAG_CODE_START_SOUND2 = 89; +const SWF_TAG_CODE_SYMBOL_CLASS = 76; +const SWF_TAG_CODE_VIDEO_FRAME = 61; self.SWF = { }; From 569fa991ee1a0f6510c0d894a6daf28d0dc78e48 Mon Sep 17 00:00:00 2001 From: Tobias Schneider Date: Thu, 25 Oct 2012 18:53:40 +0200 Subject: [PATCH 002/210] More fixes and cleanups. --- src/flash/display/Graphics.js | 113 +++++++++++++++++---------------- src/flash/display/MovieClip.js | 5 +- src/flash/display/Sprite.js | 11 ++-- src/swf/renderer.js | 2 +- 4 files changed, 65 insertions(+), 66 deletions(-) diff --git a/src/flash/display/Graphics.js b/src/flash/display/Graphics.js index 3b25020ea..55e2e4574 100644 --- a/src/flash/display/Graphics.js +++ b/src/flash/display/Graphics.js @@ -30,49 +30,7 @@ const GraphicsDefinition = (function () { this._subpaths = []; }, - get _currentPath() { - var path = new Kanvas.Path; - path.drawingStyles = this._drawingStyles; - path.fillStyle = this._fillStyle; - path.fillTransform = this._fillTransform; - path.strokeStyle = this._strokeStyle; - this._subpaths.push(path); - // Cache as an own property. - Object.defineProperty(this, '_currentPath', describeProperty(path)); - return path; - }, - - beginFill: function (color, alpha) { - if (alpha === undefined) - alpha = 1; - - delete this._currentPath; - - this._fillStyle = alpha ? toRgba(color, alpha) : null; - this._fillTransform = null; - }, - beginGradientFill: function (type, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPos) { - var gradient; - - if (type === 'linear') - gradient = fillContext.createLinearGradient(-819.2, 0, 819.2, 0); - else if (type == 'radial') - gradient = fillContext.createRadialGradient(819.2 * (focalPos || 0), 0, 0, 0, 0, 819.2); - else - throw ArgumentError(); - - for (var i = 0, n = colors.length; i < n; i++) - gradient.addColorStop(ratios[i], toRgba(colors[i], alphas[i])); - - this._fillStyle = gradient; - this._fillTransform = matrix; - }, - - beginBitmapFill: function (bitmap, matrix, repeat, smooth) { - //notImplemented(); - // stub this out - }, - beginFillObject: function (fill) { + _beginFillObject: function (fill) { if (fill === null) { this.endFill(); } else { @@ -104,7 +62,7 @@ const GraphicsDefinition = (function () { } } }, - beginStrokeObject: function (istroke) { + _beginStrokeObject: function (istroke) { var stroke = null; var fill = null; @@ -160,6 +118,55 @@ const GraphicsDefinition = (function () { } } }, + _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); + }, + + get _currentPath() { + var path = new Kanvas.Path; + path.drawingStyles = this._drawingStyles; + path.fillStyle = this._fillStyle; + path.fillTransform = this._fillTransform; + path.strokeStyle = this._strokeStyle; + this._subpaths.push(path); + // Cache as an own property. + Object.defineProperty(this, '_currentPath', describeProperty(path)); + return path; + }, + + beginFill: function (color, alpha) { + if (alpha === undefined) + alpha = 1; + + delete this._currentPath; + + this._fillStyle = alpha ? toRgba(color, alpha) : null; + this._fillTransform = null; + }, + beginGradientFill: function (type, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPos) { + var gradient; + + if (type === 'linear') + gradient = fillContext.createLinearGradient(-819.2, 0, 819.2, 0); + else if (type == 'radial') + gradient = fillContext.createRadialGradient(819.2 * (focalPos || 0), 0, 0, 0, 0, 819.2); + else + throw ArgumentError(); + + for (var i = 0, n = colors.length; i < n; i++) + gradient.addColorStop(ratios[i], toRgba(colors[i], alphas[i])); + + this._fillStyle = gradient; + this._fillTransform = matrix; + }, + + beginBitmapFill: function (bitmap, matrix, repeat, smooth) { + //notImplemented(); + // stub this out + }, clear: function () { delete this._currentPath; @@ -182,11 +189,11 @@ const GraphicsDefinition = (function () { for (var i = 0, n = graphicsData.length; i < n; i++) { var item = graphicsData[i]; if (item.__isIGraphicsPath__) - this.drawPathObject(item); + this._drawPathObject(item); else if (item.__isIGraphicsFill__) - this.beginFillObject(item); + this._beginFillObject(item); else if (item.__isIGraphicsStroke__) - this.beginStrokeObject(item); + this._beginStrokeObject(item); } }, drawPath: function (commands, data, winding) { @@ -214,12 +221,6 @@ const GraphicsDefinition = (function () { } } }, - 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); - }, drawRect: function (x, y, w, h) { if (isNaN(w + h)) throw ArgumentError(); @@ -275,11 +276,11 @@ const GraphicsDefinition = (function () { this._strokeStyle = null; } }, - moveTo: function (x, y) { - this._currentPath.moveTo(x, y); - }, lineTo: function (x, y) { this._currentPath.lineTo(x, y); + }, + moveTo: function (x, y) { + this._currentPath.moveTo(x, y); } }; diff --git a/src/flash/display/MovieClip.js b/src/flash/display/MovieClip.js index 3071d0024..83a116151 100644 --- a/src/flash/display/MovieClip.js +++ b/src/flash/display/MovieClip.js @@ -72,9 +72,8 @@ const MovieClipDefinition = (function () { if (cmd.symbolId) { var index = 0; - var symbolInfo = loader._symbols[cmd.symbolId]; - var symbolClass = avm2.systemDomain.getClass(symbolInfo.className); - var symbolInfo = loader.getSymbolInfoById(cmd.symbolId); + var symbolPromise = loader._dictionary[cmd.symbolId]; + var symbolInfo = symbolPromise.value; // HACK application domain may have the symbol class -- // checking which domain has a symbol class var symbolClass = avm2.systemDomain.findClass(symbolInfo.className) ? diff --git a/src/flash/display/Sprite.js b/src/flash/display/Sprite.js index 2c2043986..afb5ba9d3 100644 --- a/src/flash/display/Sprite.js +++ b/src/flash/display/Sprite.js @@ -11,6 +11,10 @@ const SpriteDefinition = (function () { } }, + _constructChildren: function () { + // notImplemented(); + }, + get buttonMode() { return false; }, @@ -39,10 +43,6 @@ const SpriteDefinition = (function () { notImplemented(); }, - - constructChildren: function () { - // notImplemented(); - }, startDrag: function (lockCenter, bounds) { notImplemented(); }, @@ -69,7 +69,7 @@ const SpriteDefinition = (function () { stopDrag: def.stopDrag, startTouchDrag: def.startTouchDrag, stopTouchDrag: def.stopTouchDrag, - constructChildren: def.constructChildren, + constructChildren: def._constructChildren, hitArea: desc(def, "hitArea"), useHandCursor: desc(def, "useHandCursor"), soundTransform: desc(def, "soundTransform") @@ -79,4 +79,3 @@ const SpriteDefinition = (function () { return def; }).call(this); - diff --git a/src/swf/renderer.js b/src/swf/renderer.js index c688fad84..67e48da10 100644 --- a/src/swf/renderer.js +++ b/src/swf/renderer.js @@ -90,7 +90,7 @@ function renderStage(stage, ctx) { var ctx = this.ctx; ctx.save(); - var m = child._currentTransformMatrix; + var m = child._currentTransform; ctx.transform(m.a, m.b, m.c, m.d, m.tx, m.ty); var cxform = child._cxform; From 3f041a3d1728987627a690747f2071db22554979 Mon Sep 17 00:00:00 2001 From: Tobias Schneider Date: Thu, 25 Oct 2012 18:53:57 +0200 Subject: [PATCH 003/210] Initial hitTest impl. --- src/flash/display/DisplayObject.js | 65 ++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 12 deletions(-) diff --git a/src/flash/display/DisplayObject.js b/src/flash/display/DisplayObject.js index 64424b5c9..e9f1a89fe 100644 --- a/src/flash/display/DisplayObject.js +++ b/src/flash/display/DisplayObject.js @@ -62,6 +62,57 @@ const DisplayObjectDefinition = (function () { if (this._parent !== this._stage && this._parent !== targetCoordSpace) this._parent._applyCurrentTransform(point, targetCoordSpace); }, + _hitTest: function (use_xy, x, y, useShape, hitTestObject) { + if (use_xy) { + if (useShape) { + if (this._graphics) { + var canvas = document.createElement('canvas'); + var hitCtx = canvas.getContext('kanvas-2d'); + + x += this._bbox.left; + y += this._bbox.top; + + hitCtx.transform(this._graphics._scale, 0, 0, this._graphics._scale, 0, 0); + + var subpaths = this._graphics._subpaths; + for (var i = 0, n = subpaths.length; i < n; i++) { + var path = subpaths[i]; + + hitCtx.beginPath(); + path.__draw__(hitCtx); + + if (hitCtx.isPointInPath(x, y)) + return true; + + if (path.strokeStyle && hitCtx.mozIsPointInStroke) { + hitCtx.strokeStyle = path.strokeStyle; + var drawingStyles = path.drawingStyles; + for (var prop in drawingStyles) + hitCtx[prop] = drawingStyles[prop]; + + if (hitCtx.mozIsPointInStroke(x, y)) + return true; + } + } + } + + var children = this._children; + if (children) { + for (var i = 0, n = children.length; i < n; i++) { + var child = children[i]; + if (child._hitTest(true, x, y, true)) + return true; + } + } + } + + return false; + } + + var box1 = this.getBounds(); + var box2 = hitTestObject.getBounds(); + return box1.intersects(box2); + }, _updateCurrentTransform: function () { var rotation = this._rotation / 180 * Math.PI; var scaleX = this._scaleX; @@ -276,21 +327,11 @@ const DisplayObjectDefinition = (function () { this._applyCurrentInverseTransform(result); return result; }, - hitTest: function (use_xy, x, y, useShape, hitTestObject) { - if (use_xy) { - debugger; - return false; //notImplemented(); - } else { - var box1 = this.getBounds(); - var box2 = hitTestObject.getBounds(); - return box1.intersects(box2); - } - }, hitTestObject: function (obj) { - return this.hitTest(false, 0, 0, false, obj); + return this._hitTest(false, 0, 0, false, obj); }, hitTestPoint: function (x, y, shapeFlag) { - return this.hitTest(true, x, y, shapeFlag, null); + return this._hitTest(true, x, y, shapeFlag, null); }, localToGlobal: function (pt) { var result = new flash.geom.Point(pt.x, pt.y); From 58bddc74444c2ff19d7d0ff4fe52e4e1e8a4180a Mon Sep 17 00:00:00 2001 From: Jet Villegas Date: Mon, 29 Oct 2012 04:41:46 +0100 Subject: [PATCH 004/210] Repair extension build --- extension/firefox/Makefile | 3 --- 1 file changed, 3 deletions(-) diff --git a/extension/firefox/Makefile b/extension/firefox/Makefile index 5d524f500..42e1e5bb6 100644 --- a/extension/firefox/Makefile +++ b/extension/firefox/Makefile @@ -32,9 +32,6 @@ build: mkdir content/avm2/compiler/lljs/src cp ../../src/avm2/compiler/lljs/src/*.js content/avm2/compiler/lljs/src/ # TODO src/avm2/generated/playerGlobal.swf and src/avm2/generated/builtin/builtin.abc - mkdir content/glue - mkdir content/glue/avm2 - cp ../../src/glue/avm2/*.js content/glue/avm2/ mkdir content/lib mkdir content/lib/Kanvas cp ../../lib/Kanvas/* content/lib/Kanvas/ From 3cc88aa54b5b318056acdedc2de9651588f586f7 Mon Sep 17 00:00:00 2001 From: Tobias Schneider Date: Mon, 29 Oct 2012 13:57:46 +0100 Subject: [PATCH 005/210] Improve hit testing. --- src/flash/display/DisplayObject.js | 63 ++++++++++++--------- src/flash/display/DisplayObjectContainer.js | 4 -- 2 files changed, 37 insertions(+), 30 deletions(-) diff --git a/src/flash/display/DisplayObject.js b/src/flash/display/DisplayObject.js index e9f1a89fe..5de8e3ef7 100644 --- a/src/flash/display/DisplayObject.js +++ b/src/flash/display/DisplayObject.js @@ -22,6 +22,7 @@ const DisplayObjectDefinition = (function () { this._alpha = 1; this._animated = false; this._cacheAsBitmap = false; + this._children = []; this._control = document.createElement('div'); this._bbox = null; this._currentTransform = null; @@ -44,11 +45,16 @@ const DisplayObjectDefinition = (function () { this._x = 0; this._y = 0; - this._updateCurrentTransform(); - var s = this.symbol; if (s) this._bbox = s.bbox || null; + + var canvas = document.createElement('canvas'); + canvas.width = canvas.height = 1; + var ctx = canvas.getContext('2d'); + this._hitCtx = ctx; + + this._updateCurrentTransform(); }, _applyCurrentTransform: function (point, targetCoordSpace) { @@ -66,52 +72,57 @@ const DisplayObjectDefinition = (function () { if (use_xy) { if (useShape) { if (this._graphics) { - var canvas = document.createElement('canvas'); - var hitCtx = canvas.getContext('kanvas-2d'); - - x += this._bbox.left; - y += this._bbox.top; + var hitCtx = this._hitCtx; + + hitCtx.restore(); + hitCtx.save(); + + var scale = this._graphics._scale; + if (scale !== 1) + hitCtx.scale(scale, scale); + + var pt = new flash.geom.Point(x, y); + this._applyCurrentInverseTransform(pt, this._parent); - hitCtx.transform(this._graphics._scale, 0, 0, this._graphics._scale, 0, 0); - var subpaths = this._graphics._subpaths; for (var i = 0, n = subpaths.length; i < n; i++) { var path = subpaths[i]; - + hitCtx.beginPath(); path.__draw__(hitCtx); - if (hitCtx.isPointInPath(x, y)) + if (hitCtx.isPointInPath(pt.x, pt.y)) return true; - + if (path.strokeStyle && hitCtx.mozIsPointInStroke) { hitCtx.strokeStyle = path.strokeStyle; var drawingStyles = path.drawingStyles; for (var prop in drawingStyles) hitCtx[prop] = drawingStyles[prop]; - - if (hitCtx.mozIsPointInStroke(x, y)) + + if (hitCtx.mozIsPointInStroke(pt.x, pt.y)) return true; } } } var children = this._children; - if (children) { - for (var i = 0, n = children.length; i < n; i++) { - var child = children[i]; - if (child._hitTest(true, x, y, true)) - return true; - } + for (var i = 0, n = children.length; i < n; i++) { + var child = children[i]; + if (child._hitTest(true, pt.x, pt.y, true)) + return true; } + + return false; + } else { + var bbox = this.getBounds(); + return bbox.containsPoint(pt); } - - return false; } - - var box1 = this.getBounds(); - var box2 = hitTestObject.getBounds(); - return box1.intersects(box2); + + var bbox1 = this.getBounds(); + var bbox2 = hitTestObject.getBounds(); + return bbox1.intersects(bbox2); }, _updateCurrentTransform: function () { var rotation = this._rotation / 180 * Math.PI; diff --git a/src/flash/display/DisplayObjectContainer.js b/src/flash/display/DisplayObjectContainer.js index e3b69ef79..30fdeb8ac 100644 --- a/src/flash/display/DisplayObjectContainer.js +++ b/src/flash/display/DisplayObjectContainer.js @@ -1,9 +1,5 @@ const DisplayObjectContainerDefinition = (function () { var def = { - initialize: function () { - this._children = []; - }, - get _bbox() { var children = this._children; var numChildren = children.length; From 0a6c64628f5733cf5cc94df9811256613582d331 Mon Sep 17 00:00:00 2001 From: Tobias Schneider Date: Mon, 29 Oct 2012 14:26:27 +0100 Subject: [PATCH 006/210] Fix bounding box calculation. --- src/flash/display/DisplayObject.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/flash/display/DisplayObject.js b/src/flash/display/DisplayObject.js index 5de8e3ef7..e178ffc14 100644 --- a/src/flash/display/DisplayObject.js +++ b/src/flash/display/DisplayObject.js @@ -309,13 +309,16 @@ const DisplayObjectDefinition = (function () { if (!bbox) return new flash.geom.Rectangle; - var p1 = { x: bbox.left, y: bbox.top }; + var width = bbox.right - bbox.left; + var height = bbox.bottom - bbox.top; + + var p1 = { x: 0, y: 0 }; this._applyCurrentTransform(p1, targetCoordSpace); - var p2 = { x: bbox.right, y: bbox.top }; + var p2 = { x: width, y: 0 }; this._applyCurrentTransform(p2, targetCoordSpace); - var p3 = { x: bbox.right, y: bbox.bottom }; + var p3 = { x: width, y: height }; this._applyCurrentTransform(p3, targetCoordSpace); - var p4 = { x: bbox.left, y: bbox.bottom }; + var p4 = { x: 0, y: height }; this._applyCurrentTransform(p4, targetCoordSpace); var xMin = Math.min(p1.x, p2.x, p3.x, p4.x); From 563caa149f769c9c555b9f4bcadf0dc231567957 Mon Sep 17 00:00:00 2001 From: Tobias Schneider Date: Mon, 29 Oct 2012 16:10:35 +0100 Subject: [PATCH 007/210] Initialize stage properties. --- src/flash/display/Stage.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/flash/display/Stage.js b/src/flash/display/Stage.js index 0f0e9cfd3..1e81697ca 100644 --- a/src/flash/display/Stage.js +++ b/src/flash/display/Stage.js @@ -31,7 +31,10 @@ const StageDefinition = (function () { initialize: function () { this._color = 0xFFFFFFFF; + this._focus = null; this._stage = this; + this._stageHeight = 0; + this._stageWidth = 0; this._transform = { }; }, From accb346c6efee7d0c32271d6946dcaeb46793c10 Mon Sep 17 00:00:00 2001 From: Tobias Schneider Date: Mon, 29 Oct 2012 16:10:54 +0100 Subject: [PATCH 008/210] Execute frame scripts only on real frame changes. --- src/swf/renderer.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/swf/renderer.js b/src/swf/renderer.js index 67e48da10..5ac91fa78 100644 --- a/src/swf/renderer.js +++ b/src/swf/renderer.js @@ -26,8 +26,12 @@ function renderStage(stage, ctx) { visit: function (obj) { if (MovieClipClass.isInstanceOf(obj)) { if (obj.isPlaying()) { + var currentFrame = obj._currentFrame; + obj.nextFrame(); - obj._scriptExecutionPending = true; + + if (obj._currentFrame !== currentFrame) + obj._scriptExecutionPending = true; } obj.dispatchEvent(new flash.events.Event("enterFrame")); } From 8866ee20f352dbeebb3a1068381a3fafba43e166 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 30 Oct 2012 09:55:27 -0500 Subject: [PATCH 009/210] Remove alert --- examples/inspector/inspector.html | 4 ++++ examples/inspector/inspector.js | 7 ++++++- examples/inspector/inspectorLoader.js | 3 +++ examples/inspector/style/style.css | 10 ++++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/examples/inspector/inspector.html b/examples/inspector/inspector.html index e9fb540ff..d986fcd05 100644 --- a/examples/inspector/inspector.html +++ b/examples/inspector/inspector.html @@ -139,6 +139,10 @@ -->
+
diff --git a/examples/inspector/inspector.js b/examples/inspector/inspector.js index b68434754..b53e59cda 100644 --- a/examples/inspector/inspector.js +++ b/examples/inspector/inspector.js @@ -66,10 +66,15 @@ if (rfile) { executeFile(rfile); } +function showMessage(msg) { + $('#message').text(msg); + $('#message')[0].parentElement.removeAttribute('hidden'); +} + function executeFile(file, buffer) { // All execution paths must now load AVM2. if (!state.compiler) { - alert ("Running in the Interpreter"); + showMessage("Running in the Interpreter"); } var appMode = state.compiler ? EXECUTION_MODE.COMPILE : EXECUTION_MODE.INTERPRET; if (file.endsWith(".abc")) { diff --git a/examples/inspector/inspectorLoader.js b/examples/inspector/inspectorLoader.js index df8c6b2f2..d6d14b37b 100644 --- a/examples/inspector/inspectorLoader.js +++ b/examples/inspector/inspectorLoader.js @@ -34,3 +34,6 @@ $("#openFile").click(function () { $("#files").click(); }); +$(".closeButton").click(function (event) { + event.target.parentElement.setAttribute('hidden', true); +}); diff --git a/examples/inspector/style/style.css b/examples/inspector/style/style.css index 0dd117015..c359d40bf 100644 --- a/examples/inspector/style/style.css +++ b/examples/inspector/style/style.css @@ -58,6 +58,16 @@ body { font-family: Lucida Grande, sans-serif; } +.toolbarBox.withEmphasis { + background: url(images/background-noise-toolbar.png), + -moz-linear-gradient(hsl(0,51%,36%), hsl(0,51%,18%)); + border-radius: 4px; + box-shadow: 0 1px 0 hsla(0,56%,76%,.2) inset, + 0 0 0 1px hsla(0,0%,0%,.15), + 0 10px 14px hsla(0,0%,0%,.4); + font-family: Lucida Grande, sans-serif; +} + .closeButton { float: left; width: 16px; From f5403dc3ae685e97b9ee130b887414273dc1c47a Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 30 Oct 2012 10:27:34 -0500 Subject: [PATCH 010/210] Add button tests --- examples/misc/button1.fla | Bin 0 -> 5410 bytes examples/misc/button1.swf | Bin 0 -> 1031 bytes examples/misc/button2.fla | Bin 0 -> 5435 bytes examples/misc/button2.swf | Bin 0 -> 1083 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 examples/misc/button1.fla create mode 100644 examples/misc/button1.swf create mode 100644 examples/misc/button2.fla create mode 100644 examples/misc/button2.swf diff --git a/examples/misc/button1.fla b/examples/misc/button1.fla new file mode 100644 index 0000000000000000000000000000000000000000..93d3dddf2312ca79ab09dd52f254c171ef8ba33c GIT binary patch literal 5410 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 B1Zw~Q literal 0 HcmV?d00001 diff --git a/examples/misc/button2.fla b/examples/misc/button2.fla new file mode 100644 index 0000000000000000000000000000000000000000..9e0b10e58b95537d082dc33893f639a212c4e9f5 GIT binary patch literal 5435 zcmbVQbyU<_*B&~g8A1As`H(bW4B3 z_4U>3y6->VUTd#&erN5y&sk@lvuE!|OBDr`1OUJU08(|#q^WUjP_O_1z^&dvsFeo{ z26g7=@wRo;($NGNam(roYW>3lVf0@?1Occi%jih!81epZtJ~P>@_N$T${Gs)F+;}0 z{CoRi2%7`fr&BNkCd^14{MUhVn0$`ETxloXqUcN0^(%?Vwsp9_0x~Y$L`|b+$E74 z8kLLA3>vzQ`QBxV|*MP&yxf@-d z!o;;awp{3xm3MV6+TS)wNXo8#E!9tdDpRqzIYh4+!;$}(1%iiVOuQ;KiXV$DU2ADH z9!sb$M4w&+ucloYjd9Cp=swN%x#U8_$U6eruvFowjACEK?Rs4DcnUGiOOQz{+;@*B zSF&HQeNWH6Wcw|`|MGq1gNVW0ok$F-l0@KRmv4gi8A-!~4{k6ekTGLwMep zuZ&$>4+Pxod|V(m7!IFc6B_s2U|g-rtSKS6`cw`b9vL1X8bV<$ttXq`lLPX@8zFel z$qr)%D(FA(Z;D!}$ab&xkPS7_;_e1r5yD9uws<#=Pxgqe0s>F6d~h_ml~s5@U)kj6 z)mwZO%4id?yqg@v18om%LlbGsLzXx_*53?4A2hkxo!a>>mAv`#z9afQ4iH0>3GVWa zf63(h{Qdco@d-R8%*2vR%wCVzH@_8zjV;@TWyttxrU#_dxTC)CE~ z1!=Z#Ju-Q!$2mb4%O{>WIBV_Cl<{r4QqpJMAB|0|IDG;c+PFa!wUklQ<+2Zp^sZ@( zv;F8&b$k44`JHgYJk0J{?!*WThR%FC8w7afq<2nPN_00I-dKD-Wl5s+&@7#bl`PqA zurgyt)2%bNNWyIL#eP^iG8iuNY~lG8I1sC~Bz)SK<#J6HHi>(3?su<{I9ySRVb>@hO4zyBkn4w1LUzi9~TCztlmv8 zJ+R~at7(D>_+oKR3T;50B+^1yhImHKGf~GdusB7ZV_aX?oQ|6D&Pzu9hU&_kge_63 zd+o8zOrfxv*u7Cvu*jy0(acz-GVy{wfA3RqytKQgJ=9gQM?v{)tT2F&#%~4 zH*V*DWHhQxpD+ zxO6uuW^eSTujPYeL3vD*Yd3Ya(BRjwu6$3sj>16Ax$Ubs=2@lslX$MNPf)M;1jk)3 z>AfR~`)|bhq_O~oQC`?O?~Um`hjc>7pYqh_AU6jUG?x;RzFG^75-s+vygGrDHX7U^ zy-KZfGtb`Fdq?<+D1GIW7yWuV|C?)u`-yV>Kz27#!*L!5RIAV!xpy1y&@RvnSfaAsaiwT8_*JR+h(KjK;5m-u*w8e2S3W;ylrYbI3DztY1?Sb%7tE=)Y` z@gp{MlPQfimOzQfo+T#c$RXY42)qr^EdAk!gYEEY2iqHt_tw@@UHR^wlACs)f|dBG z+(7H)lIvbD&&uJr-cPIBu|*AwECQI*XvSorB_zO>%(w`FI$SmJDHefG&OHsfwXO6F z)Ns{+=(DFUzg{}7r8uc%trIOgw?k=Hr+48F|1Lsok&4lYm>6cb=BnGVg<0NB!6tQ9 zu2Y>-(?E-Yn6s)-Hwg~L$0bh%5zr8`vl&^R_ceNX8?MGy2}mD```U%8p!Pg;(ko-f za5GZur0&HSJkMPtbJSpMRa$TKrQMH)f$1L1db0hiu04br3 znoCfg{JN3pbwhI6hne^n$pdrO4PW8wRff~#v_Tg}EiO`DOOEkB^0_y zmMp-FZ7EsTq;+GSwM0%wpr1mnouYqty^ntw8r1dRRFk=-{}?D*BD^Y1~WjF2svW;(2)ZRw4B1PwhZ?{qCAcv$xN!R;j|PLx~tCMS4l-{ zoRB1ebs*s(cX<_UpUc6La$eDVR9dra5@>DAwI$qBVX8OzVQ|Ej2Eo3tP3dfWVm~pd zaZ85UYz|IeC`;yGDTQ{^m&3=Lm?mbP_b2?+oQLx}E=l9m=Bt7ZiL_TXswYv=4p^`k zlb%-`hwdqm;n{G|Oz41#$E_5z1_`!hB}85;+CAat?2uGbI`>2>-8om`yL5Hl!1;d zZN`v1y1ssyW1x~A#GT^MLx6L~qSjnJohu`&o9xmvPBc!mff+OU>YL#9i%Bj@P0*$H ztIv66;>KLw*&}Be)kk~Mr0UCb$MUV9!s0gcLKua`gVn*V^y&E)SIvo=3@G{Yei^Mp zUySw_GC6I%8JA06S^^d~0i8M+kGBPPuv4Y>G2YHNTrVCDWtnjh0aJZ4e&{7yk7cD-4lddhgn|WEe3rY3NXokLKkrz`Z zmN=fYaj781qEmDMJUo1_(n%<~g1m(kjeC*u3ZogDQ@>n`b#!xMwb6bewk6xM7%^;S ze%P=Fohi6G@( zIpgI#c1dZzhHP`D!+KaBl|^%c1D0??rGS!JK<~zY^nJ2~qT<$tB)+>F>O zZ{9t=w~%)3^e9c3#v*K~@)9e$Ua>WYlbsf5nMSbZP__k8p6;lm$`>kXtiBtt03sgKNN=SgH4*A5{XOzi1l?g)q19+WL zl=MWltkm!?yyu;_S~(L2oUI)Nm*3-WC+puL2ImI#yB zr3$+RQ<$rDW67`3z2d!E3~$(C3~+UwE#Bs)qJ6=@AS=hf-{^xPdh_mHFV>2AsHGX- zH~fhlW&X?&Tl1tdzz0+_{wDj^BaD>8>{m&HH>$l{Uycl#)VwfnXfzJi+?r$I`$%#9 zV-h=G&+wz?41ZwZC(~1x4B_NLVBl77Yh){kGcN)Ma$py*vki~6rS)U59b$PN0~>%0 zpaEb5?gCg4-w5;|=05=g0JK*i77+5!;4MkZ5tNA4TfHTPoFIs<(8mRA>EhxDv9^Rk zpw7IWh;1xwpjP0&$)$gAO8*acBxI6XNFz4;HyR6Zgx}(?e{68c7f8O>_u-#^-pC|bF vL;s25UlG0${wt>c4Dct^eg%j?WYnLy)lx-6+{i8Ru>q+F(xc}#+XDU%*U%5< literal 0 HcmV?d00001 diff --git a/examples/misc/button2.swf b/examples/misc/button2.swf new file mode 100644 index 0000000000000000000000000000000000000000..8a33ed4585c7badc3fd8b93c62360422ebe0c931 GIT binary patch literal 1083 zcmV-B1jPG8S5psc2mk;-eG&OT8TG6h}%8@Lga=kUV=9WW9QKHKzCWJWa9bf z`@Z?-`+rS(fIkLc@f8583^12g0RZ1GXLta%L%U@hn0s>1bN$Gmvz^=tA%USN-EOzg zEf#S2OwqQswiH!YbUjZI`RLRqu$T9v2f4DGD3~a+LMI>&_T_jEo48GOa=DRg&kH89 zepG-qZlZ#PJ*5W&MJuREtV2OYB}9D zZO66c^-XPCxyqcj9#htwJ((1rxwK-Npf zx;{<5gdNeb?X*tchXsPcT2in)irHXuk2P!rQ(LRS=G(zdUDXq)Ule0 zt+t1JGE%eugW42ztX2=5XAbR;8&s>sJ-uXZZ0;6sSG_@Ek}C?G4zl+`>?KtQU>Kp; zsh!-|s@SH)U&Fa>)9X{XMjfl!Z*!n))Ug`=KQ{fVgghzCg->tY(zZ3}(4ZZ<$rWT< z3UX1rTSU85OKuF?GFmwFASuHja2*TAf=VwRonY&E7j{s-72h7)$_4Pol$6mWSe8MB z9SjEND-yjR8E|MJAITa3=OC8^0wA3MV83GM>;=fI{C0Nl!@qwj{_4Gy&N@Fop|~}= z!cK5(f&+sVkP~e0%NKu@{@{QA^# z7}ErhiuV>;A@q>OlMq^H;j;uQTeOzXk)0k==^cqu5y1gpdAwiwA_HwZN#(H<5n7*c zfd=+smBXZ@LcRGdvdChBF=;xGSSKi)H;0)GSC{sEg6Nin_UbT_y|iAz^dF8U848C% z=ny1knJky(SHGOWm^L{1R-Sy4!fyd?7TBEKN=iz1&9`6ZF3m}QZ>BXTPu zmle6YJV-hyF&VI6{4gvxL+i?>;#T0}(g7yLuqg)cfMI6STwnb>MzNAK^HlhFt}ZZi z&T_0Y|6X7H>Z3o^ek-*GMLO1J0391lYxWUSPqP%paZFmu^ws`8cq+Y5SNXaW$5Sko ze%MzLXw0dNd9|^iHWt-JMr|yq4UT@k2KR^0NeusV`92u7$5br~mueZe)<6AQXGh62 B3Mc>o literal 0 HcmV?d00001 From d08eff32ecb3073ae4c395d0d76f0d954885de9b Mon Sep 17 00:00:00 2001 From: Tobias Schneider Date: Tue, 30 Oct 2012 19:55:49 +0100 Subject: [PATCH 011/210] Carry current transform when replacing a display object. --- src/flash/display/MovieClip.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/flash/display/MovieClip.js b/src/flash/display/MovieClip.js index 83a116151..0fb201943 100644 --- a/src/flash/display/MovieClip.js +++ b/src/flash/display/MovieClip.js @@ -86,8 +86,17 @@ const MovieClipDefinition = (function () { if (!cxform) cxform = current._cxform; index = children.indexOf(current); - if (!matrix) - matrix = current.transform.matrix; + if (!matrix) { + var m = current._currentTransform; + matrix = { + a: m.a, + b: m.b, + c: m.c, + d: m.d, + tx: m.tx * 20, + ty: m.ty * 20 + }; + } replace = 1; } else { var top = null; From b6ab6d59ea266b895b4011be262e7c275f064173 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 30 Oct 2012 14:21:53 -0500 Subject: [PATCH 012/210] Fixes glue for MouseEvent and SimpleButton --- examples/inspector/inspector.html | 1 + src/flash/display/SimpleButton.js | 24 +++++++++++++++++++++--- src/flash/display/Sprite.js | 5 +++-- src/flash/events/MouseEvent.js | 2 +- src/flash/stubs.js | 2 ++ 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/examples/inspector/inspector.html b/examples/inspector/inspector.html index d986fcd05..cce75d723 100644 --- a/examples/inspector/inspector.html +++ b/examples/inspector/inspector.html @@ -94,6 +94,7 @@ + diff --git a/src/flash/display/SimpleButton.js b/src/flash/display/SimpleButton.js index 6d73e6712..df7f6866b 100644 --- a/src/flash/display/SimpleButton.js +++ b/src/flash/display/SimpleButton.js @@ -1,3 +1,21 @@ -const SimpleButtonDefinition = { - __class__: 'flash.display.SimpleButton' -}; +const SimpleButtonDefinition = (function () { + var def = { + __class__: 'flash.display.SimpleButton', + + initialize: function () { + }, + + _updateButton: function () { + } + }; + + def.__glue__ = { + native: { + instance: { + _updateButton: def._updateButton + } + } + }; + + return def; +}).call(this); diff --git a/src/flash/display/Sprite.js b/src/flash/display/Sprite.js index afb5ba9d3..c66d82b02 100644 --- a/src/flash/display/Sprite.js +++ b/src/flash/display/Sprite.js @@ -3,6 +3,7 @@ const SpriteDefinition = (function () { __class__: 'flash.display.Sprite', initialize: function () { + this._buttonMode = false; var s = this.symbol; if (s) { this._graphics = s.graphics || new flash.display.Graphics; @@ -16,10 +17,10 @@ const SpriteDefinition = (function () { }, get buttonMode() { - return false; + return this._buttonMode; }, set buttonMode(val) { - notImplemented(); + this._buttonMode = val; }, get graphics() { return this._graphics; diff --git a/src/flash/events/MouseEvent.js b/src/flash/events/MouseEvent.js index f4d460f26..b370a2cf5 100644 --- a/src/flash/events/MouseEvent.js +++ b/src/flash/events/MouseEvent.js @@ -31,7 +31,7 @@ const MouseEventDefinition = (function () { ROLL_OUT: 'public ROLL_OUT', ROLL_OVER: 'public ROLL_OVER' }, - } + }, native: { instance: { diff --git a/src/flash/stubs.js b/src/flash/stubs.js index f54bd7905..4c00ffe82 100644 --- a/src/flash/stubs.js +++ b/src/flash/stubs.js @@ -103,6 +103,7 @@ var as3error = {}; 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.geom.Point", "PointClass", PointDefinition), M("flash.geom.Rectangle", "RectangleClass", RectangleDefinition), @@ -113,6 +114,7 @@ var as3error = {}; M("flash.events.EventDispatcher", "EventDispatcherClass", EventDispatcherDefinition), M("flash.events.Event", "EventClass", EventDefinition), M("flash.events.KeyboardEvent", "KeyboardEventClass", KeyboardEventDefinition), + M("flash.events.MouseEvent", "MouseEventClass", MouseEventDefinition), M("flash.events.TimerEvent", "TimerEventClass", TimerEventDefinition), M("flash.ui.Keyboard", "KeyboardClass", KeyboardDefinition), From 41858153d55a7d88b9a7ac702028e0fe85c2c527 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Wed, 31 Oct 2012 07:08:29 -0500 Subject: [PATCH 013/210] Adds SimpleButton parsing --- src/flash/display/Loader.js | 32 ++++++++++++++++++ src/flash/display/SimpleButton.js | 56 +++++++++++++++++++++++++++++++ src/swf/button.js | 14 +++----- src/swf/renderer.js | 2 +- 4 files changed, 94 insertions(+), 10 deletions(-) diff --git a/src/flash/display/Loader.js b/src/flash/display/Loader.js index 61f80fe60..4172a9bdf 100644 --- a/src/flash/display/Loader.js +++ b/src/flash/display/Loader.js @@ -422,7 +422,39 @@ const LoaderDefinition = (function () { switch (symbol.type) { case 'button': + var states = {}; + for (var stateName in symbol.states) { + var depths = symbol.states[stateName]; + var displayList = Object.create(null); + for (var depth in depths) { + var cmd = depths[depth]; + if (cmd && cmd.symbolId) { + var itemPromise = dictionary[cmd.symbolId]; + if (itemPromise && !itemPromise.resolved) + promiseQueue.push(itemPromise); + } + displayList[depth] = cmd; + } + + var spritePromise = new Promise(); + spritePromise.resolve(displayList); + + var spriteInfo = {}; + // TODO must be Sprite or first item (if there is only one) + spriteInfo.className = 'flash.display.MovieClip'; + spriteInfo.props = { + timeline: [spritePromise], + framesLoaded: 1, + frameLabels: {}, + totalFrames: 1 + }; + states[stateName] = spriteInfo; + } + symbolInfo.className = 'flash.display.SimpleButton'; + symbolInfo.props = { + states: states + }; break; case 'font': var charset = fromCharCode.apply(null, symbol.codes); diff --git a/src/flash/display/SimpleButton.js b/src/flash/display/SimpleButton.js index df7f6866b..1d2ab2fe8 100644 --- a/src/flash/display/SimpleButton.js +++ b/src/flash/display/SimpleButton.js @@ -2,16 +2,72 @@ const SimpleButtonDefinition = (function () { var def = { __class__: 'flash.display.SimpleButton', + get downState() { + return this._downState; + }, + set downState(val) { + this._downState = val; + }, + get hitTestState() { + return this._hitTestState; + }, + set hitTestState(val) { + this._hitTestState = val; + }, + get overState() { + return this._overState; + }, + set overState(val) { + this._overState = val; + }, + get upState() { + return this._upState; + }, + set upState(val) { + this._upState = val; + }, + get _isContainer() { + return true; + }, + initialize: function () { + var s = this.symbol; + if (s) { + this._upState = createSprite(s.states.up, this); + this._overState = createSprite(s.states.over, this); + this._downState = createSprite(s.states.down, this); + this._hitTestState = createSprite(s.states.hitTest, this); + } }, _updateButton: function () { + this._children = [this.upState]; } }; + function createSprite(symbolInfo, parent) { + if (!symbolInfo) { + return null; + } + var symbolClass = avm2.systemDomain.findClass(symbolInfo.className) ? + avm2.systemDomain.getClass(symbolInfo.className) : + avm2.applicationDomain.getClass(symbolInfo.className); + var instance = symbolClass.createAsSymbol(symbolInfo.props); + symbolClass.instance.call(instance); + instance._animated = true; + instance._parent = parent; + return instance; + } + + const desc = Object.getOwnPropertyDescriptor; + def.__glue__ = { native: { instance: { + downState: desc(def, "downState"), + hitTestState: desc(def, "hitTestState"), + overState: desc(def, "overState"), + upState: desc(def, "upState"), _updateButton: def._updateButton } } diff --git a/src/swf/button.js b/src/swf/button.js index 4095d41ed..03d0a640a 100644 --- a/src/swf/button.js +++ b/src/swf/button.js @@ -2,12 +2,11 @@ function defineButton(tag, dictionary) { var characters = tag.characters; - var dependencies = []; var states = { - up: {type: 'pframe'}, - over: {type: 'pframe'}, - down: {type: 'pframe'}, - hitTest: {type: 'pframe'} + up: {}, + over: {}, + down: {}, + hitTest: {} }; var i = 0; while (character = characters[i++]) { @@ -16,7 +15,7 @@ function defineButton(tag, dictionary) { var characterItem = dictionary[character.characterId]; assert(characterItem, 'undefined character', 'button'); var entry = { - id: characterItem.id, + symbolId: characterItem.id, matrix: character.matrix }; if (character.stateUp) @@ -27,7 +26,6 @@ function defineButton(tag, dictionary) { states.down[character.depth] = entry; if (character.stateHitTest) states.hitTest[character.depth] = entry; - dependencies.push(characterItem.id); } var button = { type: 'button', @@ -35,7 +33,5 @@ function defineButton(tag, dictionary) { buttonActions: tag.buttonActions, states: states }; - if (dependencies.length) - button.require = dependencies; return button; } diff --git a/src/swf/renderer.js b/src/swf/renderer.js index eb6566cd7..313ed6425 100644 --- a/src/swf/renderer.js +++ b/src/swf/renderer.js @@ -9,7 +9,7 @@ function renderStage(stage, ctx) { for (var i = 0, n = children.length; i < n; i++) { var child = children[i]; if (child) { - var isContainer = ContainerClass.isInstanceOf(child); + var isContainer = ContainerClass.isInstanceOf(child) || child._isContainer; visitor.visit(child, isContainer); if (isContainer) { visitContainer(child, visitor); From 4f0c1d9945178816773b7b9c35abea4037c2c9a0 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Wed, 31 Oct 2012 09:11:18 -0500 Subject: [PATCH 014/210] Binds mouse events for SimpleButton --- src/flash/display/SimpleButton.js | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/flash/display/SimpleButton.js b/src/flash/display/SimpleButton.js index 1d2ab2fe8..9c7ff8bff 100644 --- a/src/flash/display/SimpleButton.js +++ b/src/flash/display/SimpleButton.js @@ -38,10 +38,38 @@ const SimpleButtonDefinition = (function () { this._downState = createSprite(s.states.down, this); this._hitTestState = createSprite(s.states.hitTest, this); } + this._isMouseDown = false; + this._isMouseOver = false; + + // binding mouse events + const MouseEventClass = avm2.systemDomain.getClass("flash.events.MouseEvent"); + this.addEventListener(MouseEventClass.MOUSE_DOWN, function (evt) { + this._isMouseDown = true; + this._updateButton(); + }.bind(this), true); + this.addEventListener(MouseEventClass.MOUSE_UP, function (evt) { + this._isMouseDown = false; + this._updateButton(); + }.bind(this), true); + this.addEventListener(MouseEventClass.MOUSE_OVER, function (evt) { + this._isMouseOver = true; + this._updateButton(); + }.bind(this), true); + this.addEventListener(MouseEventClass.MOUSE_OUT, function (evt) { + this._isMouseOver = false; + this._updateButton(); + }.bind(this), true); + }, _updateButton: function () { - this._children = [this.upState]; + var state = this.upState; + if (this._isMouseDown && this._isMouseOver && this.downState) { + state = this.downState; + } else if (this._isMouseOver && this.overState) { + state = this.overState; + } + this._children = [state]; } }; From abee20e1a8290a98f575b7772736c20690c5be0c Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Wed, 31 Oct 2012 09:42:21 -0500 Subject: [PATCH 015/210] Adjusts .gitignore --- .gitignore | 3 +++ src/avm2/tests/.gitignore | 1 + utils/.gitignore | 1 + utils/Makefile | 1 - 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index b00a84e27..8719416f4 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ src/avm2/generated/avmplus/avmplus.cpp src/avm2/utils/asc.jar src/avm2/utils/avmshell src/avm2/utils/js + +src/flash/playerGlobal.min.abc + diff --git a/src/avm2/tests/.gitignore b/src/avm2/tests/.gitignore index 73b020633..41993bd33 100644 --- a/src/avm2/tests/.gitignore +++ b/src/avm2/tests/.gitignore @@ -1,4 +1,5 @@ abc/ tamarin/ acceptance/ +regress/*/*.abc hello-world.abc diff --git a/utils/.gitignore b/utils/.gitignore index 30063803e..050e57b75 100644 --- a/utils/.gitignore +++ b/utils/.gitignore @@ -1,4 +1,5 @@ asc.jar +asc.uris.txt apparat/ flex_sdk* jsshell/ diff --git a/utils/Makefile b/utils/Makefile index a0895533d..dc706e6a2 100755 --- a/utils/Makefile +++ b/utils/Makefile @@ -51,7 +51,6 @@ install-asc: $(ASC_JAR) $(ASC_JAR): wget $(ASC_URL) -O $(ASC_JAR) - -rm asc.uris.txt install-tamarin: $(ASC_JAR) $(TAMARIN_HOME)/configure.py -rm -rf $(TAMARIN_HOME)/bin From 62b4928de0a54c31b31157b5a6f4bc3eed9fe3c0 Mon Sep 17 00:00:00 2001 From: Jet Villegas Date: Wed, 31 Oct 2012 15:46:53 +0100 Subject: [PATCH 016/210] Sync extension to inspector js inclusions. --- extension/firefox/content/web/viewer.html | 60 +++++++++++++++++++++-- 1 file changed, 55 insertions(+), 5 deletions(-) diff --git a/extension/firefox/content/web/viewer.html b/extension/firefox/content/web/viewer.html index 2d4b4426a..87eaab930 100644 --- a/extension/firefox/content/web/viewer.html +++ b/extension/firefox/content/web/viewer.html @@ -28,7 +28,7 @@ - + @@ -39,22 +39,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + - + - + + + + + + + + + + + + + + + + + diff --git a/extension/firefox/Makefile b/extension/firefox/Makefile index 42e1e5bb6..5ec286505 100644 --- a/extension/firefox/Makefile +++ b/extension/firefox/Makefile @@ -14,24 +14,33 @@ build: cp ../../src/swf/*.js content/swf/ mkdir content/flash cp ../../src/flash/*.js content/flash/ + cp ../../src/flash/playerGlobal.min.abc content/flash/ mkdir content/flash/display cp ../../src/flash/display/*.js content/flash/display/ mkdir content/flash/events cp ../../src/flash/events/*.js content/flash/events/ mkdir content/flash/geom cp ../../src/flash/geom/*.js content/flash/geom/ + mkdir content/flash/media + cp ../../src/flash/media/*.js content/flash/media/ + mkdir content/flash/net + cp ../../src/flash/net/*.js content/flash/net/ + mkdir content/flash/text + cp ../../src/flash/text/*.js content/flash/text/ mkdir content/flash/ui cp ../../src/flash/ui/*.js content/flash/ui/ + mkdir content/flash/utils + cp ../../src/flash/utils/*.js content/flash/utils/ mkdir content/avm1 cp ../../src/avm1/*.js content/avm1/ mkdir content/avm2 cp ../../src/avm2/*.js content/avm2/ mkdir content/avm2/compiler cp ../../src/avm2/compiler/*.js content/avm2/compiler/ - mkdir content/avm2/compiler/lljs - mkdir content/avm2/compiler/lljs/src + mkdir -p content/avm2/compiler/lljs/src cp ../../src/avm2/compiler/lljs/src/*.js content/avm2/compiler/lljs/src/ - # TODO src/avm2/generated/playerGlobal.swf and src/avm2/generated/builtin/builtin.abc + mkdir -p content/avm2/generated/builtin + cp ../../src/avm2/generated/builtin/builtin.abc content/avm2/generated/builtin/ mkdir content/lib mkdir content/lib/Kanvas cp ../../lib/Kanvas/* content/lib/Kanvas/ diff --git a/extension/firefox/content/web/avm2utils.js b/extension/firefox/content/web/avm2utils.js new file mode 100644 index 000000000..c00ebe66d --- /dev/null +++ b/extension/firefox/content/web/avm2utils.js @@ -0,0 +1,61 @@ +enableVerifier.value = true; +enableOpt.value = true; +enableInlineCaching.value = true; +release = true; + +var avm2Root = SHUMWAY_ROOT + "avm2/"; +var builtinPath = avm2Root + "generated/builtin/builtin.abc"; +var libraryPath = avm2Root + "generated/shell/shell.abc"; +var playerGlobalPath = SHUMWAY_ROOT + "flash/playerGlobal.min.abc"; + +var BinaryFileReader = (function binaryFileReader() { + function constructor(url, responseType) { + this.url = url; + this.responseType = responseType || "arraybuffer"; + } + + constructor.prototype = { + readAll: function(progress, complete) { + 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) { + complete(null, xhr.statusText); + return; + } + complete(xhr.response); + } + } + xhr.setRequestHeader("If-Modified-Since", "Fri, 01 Jan 1960 00:00:00 GMT"); // no-cache + xhr.send(null); + } + }; + return constructor; +})(); + +// avm2 must be global. +var avm2; + +function createAVM2(builtinPath, libraryPath, sysMode, appMode, next) { + assert (builtinPath); + new BinaryFileReader(builtinPath).readAll(null, function (buffer) { + avm2 = new AVM2(sysMode, appMode); + avm2.systemDomain.executeAbc(new AbcFile(new Uint8Array(buffer), "builtin.abc")); + if (libraryPath) { + new BinaryFileReader(libraryPath).readAll(null, function (buffer) { + avm2.systemDomain.executeAbc(new AbcFile(new Uint8Array(buffer), libraryPath)); + next(avm2); + }); + } else { + next(avm2); + } + }); +} diff --git a/extension/firefox/content/web/viewer.html b/extension/firefox/content/web/viewer.html index 87eaab930..969fe4f99 100644 --- a/extension/firefox/content/web/viewer.html +++ b/extension/firefox/content/web/viewer.html @@ -5,7 +5,11 @@ Shumway viewer + + @@ -28,9 +32,6 @@ - - - @@ -43,6 +44,17 @@ + + + @@ -58,13 +70,10 @@ - - - - - - + + + @@ -201,7 +210,10 @@ function parseSwf(url, file) { console.log("Parsing " + url + "..."); - SWF.embed(file, document.getElementById("viewer")); + function terminate() {} + createAVM2(builtinPath, playerGlobalPath, EXECUTION_MODE.INTERPRET, EXECUTION_MODE.COMPILE, function (avm2) { + SWF.embed(file, document.getElementById("viewer"), { onComplete: terminate }); + }); } diff --git a/extension/firefox/install.rdf b/extension/firefox/install.rdf index ee2a88708..09da9580e 100644 --- a/extension/firefox/install.rdf +++ b/extension/firefox/install.rdf @@ -6,15 +6,15 @@ shumway@research.mozilla.org shumway - 0.2.1 + 0.2.2 chrome://shumway/skin/logo.png {ec8030f7-c20a-464f-9b0e-13a3a9e97384} - 10.0 - 17.0a1 + 16.0 + 19.0a1 @@ -22,8 +22,8 @@ {aa3c5121-dab2-40e2-81ca-7ea25febc110} - 10.0 - 17.0a1 + 16.0 + 19.0a1 diff --git a/src/flash/display/Loader.js b/src/flash/display/Loader.js index 4172a9bdf..2acf2ee40 100644 --- a/src/flash/display/Loader.js +++ b/src/flash/display/Loader.js @@ -1,6 +1,6 @@ const LoaderDefinition = (function () { const WORKERS_ENABLED = true; - const LOADER_PATH = 'src/flash/display/Loader.js'; + const LOADER_PATH = 'flash/display/Loader.js'; const WORKER_SCRIPTS = [ '../../../lib/DataView.js/DataView.js', From c1e12d6fb52e7ae260517848d580e648801f5ef7 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Wed, 31 Oct 2012 11:45:55 -0500 Subject: [PATCH 018/210] Fixes canvas scaling/aligning --- src/swf/renderer.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/swf/renderer.js b/src/swf/renderer.js index 313ed6425..ce9912267 100644 --- a/src/swf/renderer.js +++ b/src/swf/renderer.js @@ -63,8 +63,9 @@ function renderStage(stage, ctx) { var frameWidth = ctx.canvas.width; var frameHeight = ctx.canvas.height; - var scaleX = frameWidth / stage.stageWidth; - var scaleY = frameHeight / stage.stageHeight; + var scaleX = frameWidth / stage._stageWidth; + var scaleY = frameHeight / stage._stageHeight; + var scale = Math.min(scaleX, scaleY); var offsetX = (frameWidth - scale * stage.stageWidth) / 2; var offsetY = (frameHeight - scale * stage.stageHeight) / 2; @@ -72,6 +73,7 @@ function renderStage(stage, ctx) { ctx.clearRect(0, 0, frameWidth, frameHeight); ctx.save(); ctx.translate(offsetX, offsetY); + ctx.scale(scale, scale); ctx.canvas.currentTransform = { scale: scale, From a4ed1c82a1ba28cdaaf2f49503cd2c2e4a76033d Mon Sep 17 00:00:00 2001 From: Tobias Schneider Date: Wed, 31 Oct 2012 22:45:08 +0100 Subject: [PATCH 019/210] Sync dom shadow with display list. --- src/flash/display/DisplayObjectContainer.js | 4 ++++ src/flash/display/MovieClip.js | 6 ++++++ src/swf/embed.js | 5 ++++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/flash/display/DisplayObjectContainer.js b/src/flash/display/DisplayObjectContainer.js index 30fdeb8ac..35f4c2438 100644 --- a/src/flash/display/DisplayObjectContainer.js +++ b/src/flash/display/DisplayObjectContainer.js @@ -82,6 +82,8 @@ const DisplayObjectContainerDefinition = (function () { child._owned = false; child._parent = this; + this._control.appendChild(child._control); + return child; }, areInaccessibleObjectsUnderPoint: function (pt) { @@ -137,6 +139,8 @@ const DisplayObjectContainerDefinition = (function () { children.splice(index, 1); child._parent = null; + this._control.removeChild(child._control); + return child; }, setChildIndex: function (child, index) { diff --git a/src/flash/display/MovieClip.js b/src/flash/display/MovieClip.js index 0fb201943..353176e75 100644 --- a/src/flash/display/MovieClip.js +++ b/src/flash/display/MovieClip.js @@ -59,6 +59,7 @@ const MovieClipDefinition = (function () { if (current && current._owned) { var index = children.indexOf(current); children.splice(index, 1); + this._control.removeChild(current._control); if (depth <= highestDepth) depthMap[depth] = undefined; @@ -131,6 +132,11 @@ const MovieClipDefinition = (function () { instance._animated = true; instance._owned = true; instance._parent = this; + + if (replace) + this._control.replaceChild(instance._control, current._control); + else + this._control.appendChild(instance._control); } else if (current && current._animated) { target = current; } diff --git a/src/swf/embed.js b/src/swf/embed.js index 9091c4834..bf5632327 100644 --- a/src/swf/embed.js +++ b/src/swf/embed.js @@ -43,7 +43,10 @@ SWF.embed = function(file, container, options) { stage._color = bgcolor; canvas.style.background = toStringRgba(bgcolor); - stage._children[0] = loader._content; + var root = loader._content; + stage._children[0] = root; + stage._control.appendChild(root._control); + container.appendChild(canvas); renderStage(stage, ctx); }); From a3f7f9e8a3617b90c880f809440a2e99552a964c Mon Sep 17 00:00:00 2001 From: Tobias Schneider Date: Wed, 31 Oct 2012 23:30:10 +0100 Subject: [PATCH 020/210] Support hitArea, map it to hitTestState for SimpleButtons. --- src/flash/display/DisplayObject.js | 1 + src/flash/display/SimpleButton.js | 16 ++++++++-------- src/flash/display/Sprite.js | 4 ++-- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/flash/display/DisplayObject.js b/src/flash/display/DisplayObject.js index e178ffc14..9ede761e2 100644 --- a/src/flash/display/DisplayObject.js +++ b/src/flash/display/DisplayObject.js @@ -28,6 +28,7 @@ const DisplayObjectDefinition = (function () { this._currentTransform = null; this._cxform = null; this._graphics = null; + this._hitArea = null; this._loaderInfo = null; this._mouseX = 0; this._mouseY = 0; diff --git a/src/flash/display/SimpleButton.js b/src/flash/display/SimpleButton.js index 9c7ff8bff..34db65170 100644 --- a/src/flash/display/SimpleButton.js +++ b/src/flash/display/SimpleButton.js @@ -9,10 +9,10 @@ const SimpleButtonDefinition = (function () { this._downState = val; }, get hitTestState() { - return this._hitTestState; + return this._hitArea; }, set hitTestState(val) { - this._hitTestState = val; + this._hitArea = val; }, get overState() { return this._overState; @@ -36,7 +36,7 @@ const SimpleButtonDefinition = (function () { this._upState = createSprite(s.states.up, this); this._overState = createSprite(s.states.over, this); this._downState = createSprite(s.states.down, this); - this._hitTestState = createSprite(s.states.hitTest, this); + this._hitArea = createSprite(s.states.hitTest, this); } this._isMouseDown = false; this._isMouseOver = false; @@ -63,11 +63,11 @@ const SimpleButtonDefinition = (function () { }, _updateButton: function () { - var state = this.upState; - if (this._isMouseDown && this._isMouseOver && this.downState) { - state = this.downState; - } else if (this._isMouseOver && this.overState) { - state = this.overState; + var state = this._upState; + if (this._isMouseDown && this._isMouseOver && this._downState) { + state = this._downState; + } else if (this._isMouseOver && this._overState) { + state = this._overState; } this._children = [state]; } diff --git a/src/flash/display/Sprite.js b/src/flash/display/Sprite.js index c66d82b02..09b091d0e 100644 --- a/src/flash/display/Sprite.js +++ b/src/flash/display/Sprite.js @@ -26,10 +26,10 @@ const SpriteDefinition = (function () { return this._graphics; }, get hitArea() { - return null; + return this._hitArea; }, set hitArea(val) { - notImplemented(); + this._hitArea = val; }, get soundTransform() { notImplemented(); From 6119b8e44cadfe5bc3ef8ef8acdbaa3dbfd9d50b Mon Sep 17 00:00:00 2001 From: Tobias Schneider Date: Wed, 31 Oct 2012 23:30:51 +0100 Subject: [PATCH 021/210] Initial mouse support. --- src/swf/renderer.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/swf/renderer.js b/src/swf/renderer.js index ce9912267..8a58d68e0 100644 --- a/src/swf/renderer.js +++ b/src/swf/renderer.js @@ -94,6 +94,10 @@ function renderStage(stage, ctx) { this.ctx.restore(); }, visit: function (child, isContainer) { + var hitTest = false; + var pt = new flash.geom.Point(stage._mouseX, stage._mouseY); + child._applyCurrentInverseTransform(pt, child._parent); + var ctx = this.ctx; ctx.save(); @@ -136,6 +140,10 @@ function renderStage(stage, ctx) { ctx[prop] = drawingStyles[prop]; ctx.stroke(path); } + + if (ctx.isPointInPath(pt.x, pt.y) || + (ctx.mozIsPointInStroke && ctx.mozIsPointInStroke(pt.x, pt.y))) + hitTest = true; } } @@ -147,6 +155,28 @@ function renderStage(stage, ctx) { // letting the container to restore transforms after all children are painted ctx.restore(); } + + if (child._hitArea) { + // Temporary hack + child._hitArea.nextFrame(); + + hitTest = child._hitArea._hitTest(true, pt.x, pt.y, true); + } + + if (hitTest) { + if (child._mouseOver) { + child.dispatchEvent(new flash.events.MouseEvent('mouseMove')); + } else { + child._mouseOver = true; + + child.dispatchEvent(new flash.events.MouseEvent('mouseOver')); + } + } else { + if (child._mouseOver) { + child._mouseOver = false; + child.dispatchEvent(new flash.events.MouseEvent('mouseOut')); + } + } } }; From b3e476769a896fd4544fc923b1a02adf1460d4ca Mon Sep 17 00:00:00 2001 From: Tobias Schneider Date: Wed, 31 Oct 2012 23:38:35 +0100 Subject: [PATCH 022/210] Fix calculation of stage offsets. --- src/swf/embed.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/swf/embed.js b/src/swf/embed.js index bf5632327..e9e861ce9 100644 --- a/src/swf/embed.js +++ b/src/swf/embed.js @@ -35,8 +35,18 @@ SWF.embed = function(file, container, options) { ShumwayKeyboardListener.focus = stage; }); canvas.addEventListener('mousemove', function (domEvt) { - stage._mouseX = domEvt.pageX - this.offsetLeft; - stage._mouseY = domEvt.pageY - this.offsetTop; + var node = this; + var left = 0; + var top = 0; + if (node.offsetParent) { + do { + left += node.offsetLeft; + top += node.offsetTop; + } while (node = node.offsetParent); + } + + stage._mouseX = domEvt.pageX - left; + stage._mouseY = domEvt.pageY - top; }); var bgcolor = loaderInfo._backgroundColor; From 7f265aac9d6c01e7fe9f8c1f3a699bb382581edf Mon Sep 17 00:00:00 2001 From: Tobias Schneider Date: Thu, 1 Nov 2012 00:08:10 +0100 Subject: [PATCH 023/210] Make hitArea a property of InteractiveObject. --- src/flash/display/DisplayObject.js | 1 - src/flash/display/InteractiveObject.js | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flash/display/DisplayObject.js b/src/flash/display/DisplayObject.js index 9ede761e2..e178ffc14 100644 --- a/src/flash/display/DisplayObject.js +++ b/src/flash/display/DisplayObject.js @@ -28,7 +28,6 @@ const DisplayObjectDefinition = (function () { this._currentTransform = null; this._cxform = null; this._graphics = null; - this._hitArea = null; this._loaderInfo = null; this._mouseX = 0; this._mouseY = 0; diff --git a/src/flash/display/InteractiveObject.js b/src/flash/display/InteractiveObject.js index 4aa676dfb..1fc82501b 100644 --- a/src/flash/display/InteractiveObject.js +++ b/src/flash/display/InteractiveObject.js @@ -2,6 +2,7 @@ const InteractiveObjectDefinition = (function () { var def = { initialize: function () { this._control = document.createElement('div'); + this._hitArea = null; }, get accessibilityImplementation() { From 9c80c97bdc08abc5a3374f2da6f5920c4213d0f3 Mon Sep 17 00:00:00 2001 From: Tobias Schneider Date: Thu, 1 Nov 2012 00:09:00 +0100 Subject: [PATCH 024/210] Hit test InteractiveObject istances only. --- src/swf/renderer.js | 56 ++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/src/swf/renderer.js b/src/swf/renderer.js index 8a58d68e0..658682dfa 100644 --- a/src/swf/renderer.js +++ b/src/swf/renderer.js @@ -2,18 +2,19 @@ function renderStage(stage, ctx) { // All the visitors close over this class to do instance testing. const MovieClipClass = avm2.systemDomain.getClass("flash.display.MovieClip"); const ContainerClass = avm2.systemDomain.getClass("flash.display.DisplayObjectContainer"); + const InteractiveClass = avm2.systemDomain.getClass("flash.display.InteractiveObject"); - function visitContainer(container, visitor) { + function visitContainer(container, visitor, interactiveParent) { var children = container._children; visitor.childrenStart(container); for (var i = 0, n = children.length; i < n; i++) { var child = children[i]; if (child) { var isContainer = ContainerClass.isInstanceOf(child) || child._isContainer; - visitor.visit(child, isContainer); - if (isContainer) { - visitContainer(child, visitor); - } + var interactiveParent = InteractiveClass.isInstanceOf(child) ? child : interactiveParent; + visitor.visit(child, isContainer, interactiveParent); + if (isContainer) + visitContainer(child, visitor, interactiveParent); } } visitor.childrenEnd(container); @@ -93,10 +94,12 @@ function renderStage(stage, ctx) { this.depth--; this.ctx.restore(); }, - visit: function (child, isContainer) { + visit: function (child, isContainer, interactiveParent) { var hitTest = false; - var pt = new flash.geom.Point(stage._mouseX, stage._mouseY); - child._applyCurrentInverseTransform(pt, child._parent); + if (interactiveParent) { + var pt = new flash.geom.Point(stage._mouseX, stage._mouseY); + child._applyCurrentInverseTransform(pt, child._parent); + } var ctx = this.ctx; ctx.save(); @@ -141,7 +144,7 @@ function renderStage(stage, ctx) { ctx.stroke(path); } - if (ctx.isPointInPath(pt.x, pt.y) || + if (interactiveParent && ctx.isPointInPath(pt.x, pt.y) || (ctx.mozIsPointInStroke && ctx.mozIsPointInStroke(pt.x, pt.y))) hitTest = true; } @@ -156,25 +159,26 @@ function renderStage(stage, ctx) { ctx.restore(); } - if (child._hitArea) { - // Temporary hack - child._hitArea.nextFrame(); + if (interactiveParent) { + if (child._hitArea) { + // Temporary hack + child._hitArea.nextFrame(); - hitTest = child._hitArea._hitTest(true, pt.x, pt.y, true); - } - - if (hitTest) { - if (child._mouseOver) { - child.dispatchEvent(new flash.events.MouseEvent('mouseMove')); - } else { - child._mouseOver = true; - - child.dispatchEvent(new flash.events.MouseEvent('mouseOver')); + hitTest = child._hitArea._hitTest(true, pt.x, pt.y, true); } - } else { - if (child._mouseOver) { - child._mouseOver = false; - child.dispatchEvent(new flash.events.MouseEvent('mouseOut')); + + if (interactiveParent && hitTest) { + if (interactiveParent._mouseOver) { + interactiveParent.dispatchEvent(new flash.events.MouseEvent('mouseMove')); + } else { + interactiveParent._mouseOver = true; + interactiveParent.dispatchEvent(new flash.events.MouseEvent('mouseOver')); + } + } else { + if (interactiveParent._mouseOver) { + interactiveParent._mouseOver = false; + interactiveParent.dispatchEvent(new flash.events.MouseEvent('mouseOut')); + } } } } From 496554fc4f4d0b90c4400221c0dca78141585783 Mon Sep 17 00:00:00 2001 From: Tobias Schneider Date: Thu, 1 Nov 2012 00:17:49 +0100 Subject: [PATCH 025/210] Optimize mouse support. --- src/swf/renderer.js | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/src/swf/renderer.js b/src/swf/renderer.js index 658682dfa..8b7391de8 100644 --- a/src/swf/renderer.js +++ b/src/swf/renderer.js @@ -96,9 +96,21 @@ function renderStage(stage, ctx) { }, visit: function (child, isContainer, interactiveParent) { var hitTest = false; + var hitTestShape = false; + if (interactiveParent) { var pt = new flash.geom.Point(stage._mouseX, stage._mouseY); - child._applyCurrentInverseTransform(pt, child._parent); + child._applyCurrentInverseTransform(pt, child._parent); + + if (child._hitArea) { + // Temporary hack + child._hitArea.nextFrame(); + + hitTest = child._hitArea._hitTest(true, pt.x, pt.y, true); + } + + if (!hitTest) + hitTestShape = true; } var ctx = this.ctx; @@ -144,7 +156,7 @@ function renderStage(stage, ctx) { ctx.stroke(path); } - if (interactiveParent && ctx.isPointInPath(pt.x, pt.y) || + if (hitTestShape && ctx.isPointInPath(pt.x, pt.y) || (ctx.mozIsPointInStroke && ctx.mozIsPointInStroke(pt.x, pt.y))) hitTest = true; } @@ -159,26 +171,17 @@ function renderStage(stage, ctx) { ctx.restore(); } - if (interactiveParent) { - if (child._hitArea) { - // Temporary hack - child._hitArea.nextFrame(); - - hitTest = child._hitArea._hitTest(true, pt.x, pt.y, true); - } - - if (interactiveParent && hitTest) { - if (interactiveParent._mouseOver) { - interactiveParent.dispatchEvent(new flash.events.MouseEvent('mouseMove')); - } else { - interactiveParent._mouseOver = true; - interactiveParent.dispatchEvent(new flash.events.MouseEvent('mouseOver')); - } + if (interactiveParent && hitTest) { + if (interactiveParent._mouseOver) { + interactiveParent.dispatchEvent(new flash.events.MouseEvent('mouseMove')); } else { - if (interactiveParent._mouseOver) { - interactiveParent._mouseOver = false; - interactiveParent.dispatchEvent(new flash.events.MouseEvent('mouseOut')); - } + interactiveParent._mouseOver = true; + interactiveParent.dispatchEvent(new flash.events.MouseEvent('mouseOver')); + } + } else { + if (interactiveParent._mouseOver) { + interactiveParent._mouseOver = false; + interactiveParent.dispatchEvent(new flash.events.MouseEvent('mouseOut')); } } } From 2316c164951f6b47208380fde7e2c83d8a55a82f Mon Sep 17 00:00:00 2001 From: Tobias Schneider Date: Thu, 1 Nov 2012 00:32:59 +0100 Subject: [PATCH 026/210] Fire click events. --- src/flash/display/Stage.js | 1 + src/swf/embed.js | 3 +++ src/swf/renderer.js | 5 +++++ 3 files changed, 9 insertions(+) diff --git a/src/flash/display/Stage.js b/src/flash/display/Stage.js index 1e81697ca..1f5fb83ca 100644 --- a/src/flash/display/Stage.js +++ b/src/flash/display/Stage.js @@ -32,6 +32,7 @@ const StageDefinition = (function () { initialize: function () { this._color = 0xFFFFFFFF; this._focus = null; + this._clickTarget = null; this._stage = this; this._stageHeight = 0; this._stageWidth = 0; diff --git a/src/swf/embed.js b/src/swf/embed.js index e9e861ce9..4de644e6d 100644 --- a/src/swf/embed.js +++ b/src/swf/embed.js @@ -33,6 +33,9 @@ SWF.embed = function(file, container, options) { canvas.addEventListener('click', function () { ShumwayKeyboardListener.focus = stage; + + if (stage._clickTarget) + stage._clickTarget.dispatchEvent(new flash.events.MouseEvent('click')); }); canvas.addEventListener('mousemove', function (domEvt) { var node = this; diff --git a/src/swf/renderer.js b/src/swf/renderer.js index 8b7391de8..2e714c131 100644 --- a/src/swf/renderer.js +++ b/src/swf/renderer.js @@ -178,11 +178,16 @@ function renderStage(stage, ctx) { interactiveParent._mouseOver = true; interactiveParent.dispatchEvent(new flash.events.MouseEvent('mouseOver')); } + + stage._clickTarget = interactiveParent; } else { if (interactiveParent._mouseOver) { interactiveParent._mouseOver = false; interactiveParent.dispatchEvent(new flash.events.MouseEvent('mouseOut')); } + + if (stage._mouseTarget === interactiveParent) + stage._clickTarget = null; } } }; From 05b99e30a089be2d1e416182fc2f262d440e316c Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Wed, 31 Oct 2012 18:04:25 -0500 Subject: [PATCH 027/210] AVM1 on AVM2 implementation --- src/avm1/classes.js | 16 +++-- src/avm1/globals.js | 4 +- src/avm1/interpreter.js | 1 + src/flash/display/Loader.js | 102 ++++++++++++++++++++++-------- src/flash/display/MovieClip.js | 77 ++++++++++++++++++++++ src/flash/events/KeyboardEvent.js | 3 + 6 files changed, 169 insertions(+), 34 deletions(-) diff --git a/src/avm1/classes.js b/src/avm1/classes.js index 80adbf6c2..4ee317982 100644 --- a/src/avm1/classes.js +++ b/src/avm1/classes.js @@ -281,10 +281,12 @@ AS2MovieClip.prototype = Object.create({}, { enumerable: true }, hitTest: { - value: function hitTest(x, y, shapeFlag, target) { - if (x instanceof AS2MovieClip) - x = x.$nativeObject; - return this.$nativeObject.hitTest(x, y, shapeFlag, target); + value: function hitTest(x, y, shapeFlag) { + if (x instanceof AS2MovieClip) { + return this.$nativeObject.hitTestObject(x.$nativeObject); + } else { + return this.$nativeObject.hitTestPoint(x, y, shapeFlag); + } }, enumerable: false }, @@ -1130,11 +1132,11 @@ AS2Stage.prototype = Object.create({}, { } }); AS2Broadcaster.initialize(AS2Stage); - +/* var flash = {}; flash.geom = {}; - +*/ function AS2Rectangle(x, y, width, height) { this.x = x; this.y = y; @@ -1144,6 +1146,7 @@ function AS2Rectangle(x, y, width, height) { AS2Rectangle.prototype = Object.create({}, { // TODO methods }); +/* flash.geom.Rectangle = AS2Rectangle; // TODO flash.geom.Point @@ -1227,6 +1230,7 @@ flash.utils = { setInterval: window.setInterval, setTimeout: window.setTimeout }; +*/ // Built-in classes modifications diff --git a/src/avm1/globals.js b/src/avm1/globals.js index d949a05e3..c542ec6ee 100644 --- a/src/avm1/globals.js +++ b/src/avm1/globals.js @@ -39,7 +39,9 @@ AS2Globals.prototype = { return nativeTarget[PropertiesIndexMap[index]]; }, getTimer: function() { - return flash.utils.getTimer(); + var getTimer = avm2.applicationDomain.getProperty( + Multiname.fromSimpleName('flash.utils.getTimer'), true, true); + return getTimer(); }, getURL: function(url, target, method) { var request = new AS2URLRequest(url); diff --git a/src/avm1/interpreter.js b/src/avm1/interpreter.js index e5e235514..4772d2598 100644 --- a/src/avm1/interpreter.js +++ b/src/avm1/interpreter.js @@ -43,6 +43,7 @@ function executeActions(actionsData, context, scope) { try { AS2Context.instance = context; context.defaultTarget = scope; + context.globals['this'] = scope; actionTracer.message('ActionScript Execution Starts'); actionTracer.indent(); interpretActions(actionsData, scopeContainer, null, []); diff --git a/src/flash/display/Loader.js b/src/flash/display/Loader.js index 2acf2ee40..bbe4646ed 100644 --- a/src/flash/display/Loader.js +++ b/src/flash/display/Loader.js @@ -82,16 +82,18 @@ const LoaderDefinition = (function () { var frame = { type: 'frame' }; var frames = []; var tags = swfTag.tags; + var frameScripts = null; + var frameIndex = 0; for (var i = 0, n = tags.length; i < n; i++) { var tag = tags[i]; switch (tag.code) { - //case SWF_TAG_CODE_DO_ACTION: - // var actionBlocks = frame.actionBlocks; - // if (!actionBlocks) - // frame.actionBlocks = [tag.actionsData]; - // else - // actionBlocks.push(tag.actionsData); - // break; + case SWF_TAG_CODE_DO_ACTION: + if (!frameScripts) + frameScripts = []; + frameScripts.push(frameIndex); + frameScripts.push(tag.actionsData); + break; + // case SWF_TAG_CODE_DO_INIT_ACTION: ?? case SWF_TAG_CODE_FRAME_LABEL: frame.labelName = tag.name; break; @@ -113,6 +115,7 @@ const LoaderDefinition = (function () { i++; repeat++; } + frameIndex += repeat; if (repeat > 1) frame.repeat = repeat; frame.depths = depths; @@ -126,7 +129,8 @@ const LoaderDefinition = (function () { type: 'sprite', id: swfTag.id, frameCount: swfTag.frameCount, - frames: frames + frames: frames, + frameScripts: frameScripts }; break; case SWF_TAG_CODE_DEFINE_TEXT: @@ -173,21 +177,20 @@ const LoaderDefinition = (function () { else frame.abcBlocks = [tag.data]; break; - //case SWF_TAG_CODE_DO_ACTION: - // var actionBlocks = frame.actionBlocks; - // if (actionBlocks) - // actionBlocks.push(tag.actionData); - // else - // frame.actionBlocks = [tag.actionData]; - // break; - //case SWF_TAG_CODE_DO_INIT_ACTION: - // var initActionBlocks = frame.initActionBlocks; - // if (!initActionBlocks) { - // initActionBlocks = { }; - // frame.initActionBlocks = initActionBlocks; - // } - // initActionBlocks[tag.spriteId] = tag.actionsData; - // 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; + if (!initActionBlocks) { + frame.initActionBlocks = initActionBlocks = {}; + } + initActionBlocks[tag.spriteId] = tag.actionsData; + break; case SWF_TAG_CODE_EXPORT_ASSETS: case SWF_TAG_CODE_SYMBOL_CLASS: var exports = frame.exports; @@ -311,6 +314,7 @@ const LoaderDefinition = (function () { }, _commitFrame: function (frame) { var abcBlocks = frame.abcBlocks; + var actionBlocks = frame.actionBlocks; var depths = frame.depths; var exports = frame.exports; var loader = this; @@ -352,7 +356,7 @@ const LoaderDefinition = (function () { } } - if (exports) { + if (exports && loader._isAvm2Enabled) { for (var i = 0, n = exports.length; i < n; i++) { var asset = exports[i]; var symbolPromise = dictionary[asset.symbolId]; @@ -372,8 +376,8 @@ const LoaderDefinition = (function () { } var root = loader._content; - - if (!root) { + var needRootObject = !root; + if (needRootObject) { var stage = loader._stage; var rootClass = avm2.applicationDomain.getClass(val.className); @@ -389,6 +393,11 @@ const LoaderDefinition = (function () { loader._content = root; } + if (!loader._isAvm2Enabled) { + loader._initAvm1Bindings(root, needRootObject, frameNum, + actionBlocks, exports); + } + framePromise.resolve(displayList); root._framesLoaded++; @@ -404,6 +413,39 @@ const LoaderDefinition = (function () { loaderInfo.dispatchEvent(new flash.events.Event('init')); }); }, + _initAvm1Bindings: function(root, initializeRoot, frameNum, + actionBlocks, exports) { + var avm1Context = this._avm1Context; + if (initializeRoot) { + var as2Object = root._getAS2Object(); + avm1Context.globals._root = as2Object; + avm1Context.globals._level0 = as2Object; + } + if (exports) { + // HACK mocking the sound clips presence + var SoundMock = function(assets) { + var clip = { + start: function() {}, + setVolume: function() {} + }; + for (var i = 0; i < assets.length; i++) { + if (assets[i].className) { + this[assets[i].className] = clip; + } + } + }; + + var as2Object = root._getAS2Object(); + as2Object.soundmc = new SoundMock(exports); + } + if (actionBlocks) { + for (var i = 0; i < actionBlocks.length; i++) { + root.addFrameScript(frameNum - 1, function(actionBlock) { + return executeActions(actionBlock, avm1Context, avm1Context.globals._root); + }.bind(root, actionBlocks[i])); + } + } + }, _commitSymbol: function (symbol) { var dependencies = symbol.require; var dictionary = this._dictionary; @@ -499,6 +541,7 @@ const LoaderDefinition = (function () { draw: function (c, r) { return drawFn.call(this, dictionary, c, r); }, + variableName: symbol.variableName, text: symbol.value }; break; @@ -566,6 +609,7 @@ const LoaderDefinition = (function () { timeline: timeline, framesLoaded: frameCount, frameLabels: frameLabels, + frameScripts: symbol.frameScripts, totalFrames: frameCount }; break; @@ -624,7 +668,11 @@ const LoaderDefinition = (function () { if (loader._isAvm2Enabled) { loader._vmPromise.resolve(); } else { - // TODO avm1 initialization + // avm1 initialization + var loaderInfo = loader.contentLoaderInfo; + var avm1Context = new AS2Context(loaderInfo._swfVersion); + avm1Context.stage = stage; + loader._avm1Context = avm1Context; AS2Key.$bind(stage); AS2Mouse.$bind(stage); diff --git a/src/flash/display/MovieClip.js b/src/flash/display/MovieClip.js index 0fb201943..fed9c745e 100644 --- a/src/flash/display/MovieClip.js +++ b/src/flash/display/MovieClip.js @@ -128,9 +128,15 @@ const MovieClipDefinition = (function () { // constructor is not nullary. symbolClass.instance.call(instance); + if (!loader._isAvm2Enabled) { + this._initAvm1Bindings(cmd, symbolInfo.props, instance); + } + instance._animated = true; instance._owned = true; instance._parent = this; + + instance.dispatchEvent(new flash.events.Event("load")); } else if (current && current._animated) { target = current; } @@ -165,6 +171,77 @@ const MovieClipDefinition = (function () { this._currentFrame = frameNum; }, + _getAS2Object: function () { + if (!this.$as2Object) { + new AS2MovieClip().$attachNativeObject(this); + } + return this.$as2Object; + }, + _initAvm1Bindings: function (cmd, symbolProps, instance) { + var loader = this.loaderInfo._loader; + var avm1Context = loader._avm1Context; + if (symbolProps.frameScripts) { + var frameScripts = symbolProps.frameScripts; + for (var i = 0; i < frameScripts.length; i += 2) { + var frameIndex = frameScripts[i]; + var actionBlock = frameScripts[i + 1]; + instance.addFrameScript(frameIndex, function(actionBlock) { + return executeActions(actionBlock, avm1Context, this._getAS2Object()); + }.bind(instance, actionBlock)); + } + } + if (symbolProps.variableName) { + var variableName = symbolProps.variableName; + var i = variableName.lastIndexOf('.'); + var clip; + if (i >= 0) { + var targetPath = variableName.substring(0, i).split('.'); + if (targetPath[0] == '_root') { + clip = this.root._getAS2Object(); + targetPath.shift(); + } else { + clip = instance._getAS2Object(); + } + while (targetPath.length > 0) { + if (!(targetPath[0] in clip)) + throw 'Cannot find ' + variableName + ' variable'; + clip = clip[targetPath.shift()]; + } + variableName = variableName.substring(i + 1); + } else + clip = instance._getAS2Object(); + if (!(variableName in clip)) + clip[variableName] = instance.text; + delete instance.text; + Object.defineProperty(instance, 'text', { + get: function (variableName) { + return this[variableName]; + }.bind(clip, variableName), + enumerable: true + }); + } + + if (cmd.hasEvents) { + for (var i = 0; i < cmd.events.length; i++) { + var event = cmd.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); + this.addEventListener(avm2EventName, fn, false); + } + } + } + if (cmd.name) { + this._getAS2Object()[cmd.name] = instance._getAS2Object(); + } + }, get currentFrame() { return this._currentFrame; diff --git a/src/flash/events/KeyboardEvent.js b/src/flash/events/KeyboardEvent.js index 8636e00f9..59cddc6cf 100644 --- a/src/flash/events/KeyboardEvent.js +++ b/src/flash/events/KeyboardEvent.js @@ -4,6 +4,9 @@ const KeyboardEventDefinition = (function () { updateAfterEvent: function () { notImplemented(); + }, + get keyCode() { + return this.private$flash$events$KeyboardEvent$m_keyCode; } }; From 421cbfb91c61cbd086b6afead54c622264eee73e Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 6 Nov 2012 16:29:15 -0600 Subject: [PATCH 028/210] Cleanup avm1/classes.js --- src/avm1/classes.js | 365 +++++++------------------------------------- 1 file changed, 54 insertions(+), 311 deletions(-) diff --git a/src/avm1/classes.js b/src/avm1/classes.js index 4ee317982..c01951241 100644 --- a/src/avm1/classes.js +++ b/src/avm1/classes.js @@ -24,6 +24,32 @@ function proxyNativeMethod(methodName) { }; } +function proxyEventHandler(eventName, argsConverter) { + var currentHandler = null; + function handlerRunner() { + if (currentHandler) { + var args = argsConverter ? argsConverter(arguments) : null; + return currentHandler.apply(this, args); + } + } + return { + get: function() { + return handlerRunner; + }, + set: function(newHandler) { + if (currentHandler) { + this.$nativeObject.removeEventListener(eventName, currentHandler); + } + currentHandler = newHandler; + if (newHandler) { + this.$nativeObject.addEventListener(eventName, newHandler); + } + }, + configurable: false, + enumerable: false + }; +} + function createConstant(value) { return { value: value, @@ -355,108 +381,23 @@ AS2MovieClip.prototype = Object.create({}, { }, enumerable: false }, - onData: { - value: function() {}, - writable: true, - configurable: true, - enumerable: false - }, - onDragOut: { - value: function() {}, - writable: true, - configurable: true, - enumerable: false - }, - onDragOver: { - value: function() {}, - writable: true, - configurable: true, - enumerable: false - }, - onEnterFrame: { - value: function() {}, - writable: true, - configurable: true, - enumerable: false - }, - onKeyDown: { - value: function() {}, - writable: true, - configurable: true, - enumerable: false - }, - onKeyUp: { - value: function() {}, - writable: true, - configurable: true, - enumerable: false - }, - onKillFocus: { - value: function(newFocus) {}, - writable: true, - configurable: true, - enumerable: false - }, - onLoad: { - value: function() {}, - writable: true, - configurable: true, - enumerable: false - }, - onMouseDown: { - value: function() {}, - writable: true, - configurable: true, - enumerable: false - }, - onMouseUp: { - value: function() {}, - writable: true, - configurable: true, - enumerable: false - }, - onPress: { - value: function() {}, - writable: true, - configurable: true, - enumerable: false - }, - onRelease: { - value: function() {}, - writable: true, - configurable: true, - enumerable: false - }, - onReleaseOutside: { - value: function() {}, - writable: true, - configurable: true, - enumerable: false - }, - onRollOut: { - value: function() {}, - writable: true, - configurable: true, - enumerable: false - }, - onRollOver: { - value: function() {}, - writable: true, - configurable: true, - enumerable: false - }, - onSetFocus: { - value: function(oldFocus) {}, - writable: true, - configurable: true, - enumerable: false - }, - onUnload: { - value: function() {}, - writable: true, - configurable: true, - enumerable: false - }, + onData: proxyEventHandler('data'), + onDragOut: proxyEventHandler('dragOut'), + onDragOut: proxyEventHandler('dragOver'), + onEnterFrame: proxyEventHandler('enterFrame'), + onKeyDown: proxyEventHandler('keyDown'), + onKeyUp: proxyEventHandler('keyUp'), + onKillFocus: proxyEventHandler('focusOut', function(e) { return [e.relatedObject]; }), + onLoad: proxyEventHandler('load'), + onMouseDown: proxyEventHandler('mouseDown'), + onMouseUp: proxyEventHandler('mouseUp'), + onPress: proxyEventHandler('mouseDown'), + onRelease: proxyEventHandler('mouseUp'), + onReleaseOutside: proxyEventHandler('releaseOutside'), + onRollOut: proxyEventHandler('rollOut'), + onRollOver: proxyEventHandler('rollOver'), + onSetFocus: proxyEventHandler('focusIn', function(e) { return [e.relatedObject]; }), + onUnload: proxyEventHandler('unload'), opaqueBackground: { // @flash.display.DisplayObject get: function get$opaqueBackground() { return this.$nativeObject.opaqueBackground; }, set: function set$opaqueBackground(value) { this.$nativeObject.opaqueBackground = value; }, @@ -700,72 +641,17 @@ AS2Button.prototype = Object.create({}, { set: function set$_name(value) { this.$nativeObject.name = value; }, enumerable: true }, - onDragOut: { - value: function() {}, - writable: true, - configurable: true, - enumerable: false - }, - onDragOver: { - value: function() {}, - writable: true, - configurable: true, - enumerable: false - }, - onKeyDown: { - value: function() {}, - writable: true, - configurable: true, - enumerable: false - }, - onKeyUp: { - value: function() {}, - writable: true, - configurable: true, - enumerable: false - }, - onKillFocus: { - value: function(newFocus) {}, - writable: true, - configurable: true, - enumerable: false - }, - onPress: { - value: function() {}, - writable: true, - configurable: true, - enumerable: false - }, - onRelease: { - value: function() {}, - writable: true, - configurable: true, - enumerable: false - }, - onReleaseOutside: { - value: function() {}, - writable: true, - configurable: true, - enumerable: false - }, - onRollOut: { - value: function() {}, - writable: true, - configurable: true, - enumerable: false - }, - onRollOver: { - value: function() {}, - writable: true, - configurable: true, - enumerable: false - }, - onSetFocus: { - value: function(oldFocus) {}, - writable: true, - configurable: true, - enumerable: false - }, + onDragOut: proxyEventHandler('dragOut'), + onDragOut: proxyEventHandler('dragOver'), + onKeyDown: proxyEventHandler('keyDown'), + onKeyUp: proxyEventHandler('keyUp'), + onKillFocus: proxyEventHandler('focusOut', function(e) { return [e.relatedObject]; }), + onPress: proxyEventHandler('mouseDown'), + onRelease: proxyEventHandler('mouseUp'), + onReleaseOutside: proxyEventHandler('releaseOutside'), + onRollOut: proxyEventHandler('rollOut'), + onRollOver: proxyEventHandler('rollOver'), + onSetFocus: proxyEventHandler('focusIn', function(e) { return [e.relatedObject]; }), _parent: { // @flash.display.DisplayObject get: function get$_parent() { return this.$nativeObject.parent; }, set: function set$_parent(value) { this.$nativeObject.parent = value; }, @@ -944,20 +830,6 @@ defineObjectProperties(AS2Key, { } } }); -AS2Key.prototype = Object.create({}, { - onKeyDown: { - value: function () {}, - writable: true, - configurable: true, - enumerable: false - }, - onKeyUp: { - value: function () {}, - writable: true, - configurable: true, - enumerable: false - } -}); AS2Broadcaster.initialize(AS2Key); function AS2Mouse() {} @@ -1023,32 +895,6 @@ defineObjectProperties(AS2Mouse, { enumerable: false } }); -AS2Mouse.prototype = Object.create({}, { - onMouseDown: { - value: function () {}, - writable: true, - configurable: true, - enumerable: false - }, - onMouseMove: { - value: function () {}, - writable: true, - configurable: true, - enumerable: false - }, - onMouseUp: { - value: function () {}, - writable: true, - configurable: true, - enumerable: false - }, - onMouseWheel: { - value: function () {}, - writable: true, - configurable: true, - enumerable: false - } -}); AS2Broadcaster.initialize(AS2Mouse); function AS2Stage() { @@ -1117,26 +963,8 @@ defineObjectProperties(AS2Stage, { enumerable: true } }); -AS2Stage.prototype = Object.create({}, { - onFullScreen: { - value: function (bFull) {}, - writable: true, - configurable: true, - enumerable: false - }, - onResize: { - value: function () {}, - writable: true, - configurable: true, - enumerable: false - } -}); AS2Broadcaster.initialize(AS2Stage); -/* -var flash = {}; -flash.geom = {}; -*/ function AS2Rectangle(x, y, width, height) { this.x = x; this.y = y; @@ -1146,91 +974,6 @@ function AS2Rectangle(x, y, width, height) { AS2Rectangle.prototype = Object.create({}, { // TODO methods }); -/* -flash.geom.Rectangle = AS2Rectangle; - -// TODO flash.geom.Point -// TODO flash.geom.Matrix -// TODO flash.geom.ColorTransform -// TODO flash.geom.Transform - -flash.media = { -}; - -function AS2SoundMixer() { -} -defineObjectProperties(AS2SoundMixer, { - stopAll: { - value: function stopAll() { - // TODO stop all sounds - console.log('SoundMixer: stopAll'); - }, - enumerable: false - } -}); -flash.media.SoundMixer = AS2SoundMixer; - -flash.net = { - navigateToURL: function navigateToURL(request, window) { - if (request.method == 'GET') { - // HACK trying to perform simple case of the navigateToURL - window.open(request.url, window); - return; - } - throw 'Not implemented: navigateToURL'; - } -}; - -function AS2URLRequest(url) { - this.url = url; -} -AS2URLRequest.prototype = Object.create({}, { - url: { - value: null, - writable: true, - configurable: true, - enumerable: true - }, - method: { - value: 'GET', - writable: true, - configurable: true, - enumerable: true - } -}); -flash.net.URLRequest = AS2URLRequest; - -flash.system = { - fscommand: function fscommand(command, parameters) { - // TODO ignoring all fscommand - console.log('FSCommand: ' + command + '; ' + parameters); - } -}; - -function AS2Capabilities() {} -defineObjectProperties(AS2Capabilities, { - version: { - get: function get$version() { - return 'SHUMWAY ' + AS2Context.instance.swfVersion + ',0,0,0'; - }, - enumerable: true - } -}); -flash.system.Capalilities = AS2Capabilities; - -flash.utils = { - clearInterval: window.clearInterval, - clearTimeout: window.clearTimeout, - getTimer: (function() { - var startTime = Date.now(); - return (function() { - return Date.now() - startTime; - }); - })(), - setInterval: window.setInterval, - setTimeout: window.setTimeout -}; -*/ // Built-in classes modifications From 6de87b75f364e60e78f491015b14b4ecfd399565 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 6 Nov 2012 16:56:36 -0600 Subject: [PATCH 029/210] Increase extension version and remove scroll bars --- extension/firefox/content/web/viewer.html | 13 +++++++++++-- extension/firefox/install.rdf | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/extension/firefox/content/web/viewer.html b/extension/firefox/content/web/viewer.html index 969fe4f99..dcb2e4871 100644 --- a/extension/firefox/content/web/viewer.html +++ b/extension/firefox/content/web/viewer.html @@ -218,17 +218,26 @@ - - -
+ + @@ -50,9 +51,6 @@ - - - @@ -61,29 +59,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + - + - - + + + + + + + + + + + + + + + + + + + + +
+ + var SWF_PATH = "race.swf"; + createAVM2(builtinPath, playerGlobalPath, EXECUTION_MODE.INTERPRET, EXECUTION_MODE.COMPILE, function (avm2) { + function loaded() {} -
-
+
Shumway Inspector
Open File
diff --git a/examples/inspector/inspector.js b/examples/inspector/inspector.js index b53e59cda..1507e8f7f 100644 --- a/examples/inspector/inspector.js +++ b/examples/inspector/inspector.js @@ -63,6 +63,7 @@ var playerGlobalPath = "../../src/flash/playerGlobal.min.abc"; * when the page loads. */ if (rfile) { + $('#openFileToolbar')[0].setAttribute('hidden', true); executeFile(rfile); } diff --git a/web/.gitignore b/web/.gitignore new file mode 100644 index 000000000..07ed7069a --- /dev/null +++ b/web/.gitignore @@ -0,0 +1 @@ +build/* \ No newline at end of file From 692994f9a48ba4b84df4a0a9e578d2524f4814bd Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Thu, 8 Nov 2012 16:06:16 -0600 Subject: [PATCH 051/210] Extesion autoupdate --- extension/firefox/Makefile | 2 +- extension/firefox/install.rdf | 8 +++++--- extension/firefox/update.rdf | 26 ++++++++++++++++++++++++++ web/Makefile | 6 ++++-- web/build | 1 - 5 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 extension/firefox/update.rdf delete mode 160000 web/build diff --git a/extension/firefox/Makefile b/extension/firefox/Makefile index 76a177ab7..7065658df 100644 --- a/extension/firefox/Makefile +++ b/extension/firefox/Makefile @@ -3,7 +3,7 @@ build: clean # Coping extension files mkdir build - cp -R ../../LICENSE components content bootstrap.js install.rdf build/ + cp -R ../../LICENSE components content bootstrap.js install.rdf update.rdf build/ # Coping JavaScript content files mkdir build/content/swf cp ../../src/swf/*.js build/content/swf/ diff --git a/extension/firefox/install.rdf b/extension/firefox/install.rdf index 4a5f206ca..ec49188f2 100644 --- a/extension/firefox/install.rdf +++ b/extension/firefox/install.rdf @@ -6,14 +6,14 @@ shumway@research.mozilla.org shumway - 0.2.4 + 0.2.5 chrome://shumway/skin/logo.png {ec8030f7-c20a-464f-9b0e-13a3a9e97384} - 16.0 + 17.0 19.0a1 @@ -22,7 +22,7 @@ {aa3c5121-dab2-40e2-81ca-7ea25febc110} - 16.0 + 17.0 19.0a1 @@ -33,5 +33,7 @@ shumway loader https://github.com/mozilla/shumway/ 2 + + https://github.com/mozilla/shumway/raw/gh-pages/extension/firefox/update.rdf diff --git a/extension/firefox/update.rdf b/extension/firefox/update.rdf new file mode 100644 index 000000000..a19cd061a --- /dev/null +++ b/extension/firefox/update.rdf @@ -0,0 +1,26 @@ + + + + + + + + + + 0.2.5 + + + {ec8030f7-c20a-464f-9b0e-13a3a9e97384} + 17.0 + 19.* + + https://github.com/mozilla/shumway/raw/gh-pages/extensions/firefox/shumway.xpi + + + + + + + + diff --git a/web/Makefile b/web/Makefile index 6b17733d9..fa20d9895 100644 --- a/web/Makefile +++ b/web/Makefile @@ -50,6 +50,7 @@ build: clean \ # Copy extensions mkdir -p build/extension/firefox cp $(SHUMWAY_ROOT)/extension/firefox/build/shumway.xpi build/extension/firefox/ + cp $(SHUMWAY_ROOT)/extension/firefox/build/update.rdf build/extension/firefox/ # Removing hidden files -find build -name ".DS_Store" | xargs rm # Creating commit @@ -60,10 +61,11 @@ build: clean \ $(SHUMWAY_ROOT)/extension/firefox/build/shumway.xpi: $(MAKE) -C $(SHUMWAY_ROOT)/extension/firefox build -clean: - -rm -rf build $(SHUMWAY_ROOT)/src/flash/playerGlobal.min.abc: make -C $(SHUMWAY_ROOT) build-playerglobal +clean: + -rm -rf build + PHONY: build clean diff --git a/web/build b/web/build deleted file mode 160000 index fc030a7b4..000000000 --- a/web/build +++ /dev/null @@ -1 +0,0 @@ -Subproject commit fc030a7b41b13f32ea086d777f0d5286a6f663dd From a5cbcb696df43939342c8c3838ada62e056ae6f9 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Thu, 8 Nov 2012 16:13:26 -0600 Subject: [PATCH 052/210] Adjusts .gitignore --- web/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/.gitignore b/web/.gitignore index 07ed7069a..d16386367 100644 --- a/web/.gitignore +++ b/web/.gitignore @@ -1 +1 @@ -build/* \ No newline at end of file +build/ \ No newline at end of file From fd1a8e3946ce63428e736805b2f1d9b1915452ab Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Thu, 8 Nov 2012 16:17:15 -0600 Subject: [PATCH 053/210] Increase extension version --- extension/firefox/install.rdf | 2 +- extension/firefox/update.rdf | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/extension/firefox/install.rdf b/extension/firefox/install.rdf index ec49188f2..84b71fa23 100644 --- a/extension/firefox/install.rdf +++ b/extension/firefox/install.rdf @@ -6,7 +6,7 @@ shumway@research.mozilla.org shumway - 0.2.5 + 0.2.6 chrome://shumway/skin/logo.png diff --git a/extension/firefox/update.rdf b/extension/firefox/update.rdf index a19cd061a..d6b83700a 100644 --- a/extension/firefox/update.rdf +++ b/extension/firefox/update.rdf @@ -8,12 +8,12 @@ - 0.2.5 + 0.2.6 {ec8030f7-c20a-464f-9b0e-13a3a9e97384} 17.0 - 19.* + 19.0a1 https://github.com/mozilla/shumway/raw/gh-pages/extensions/firefox/shumway.xpi From 0498e6a0390e74f541310fa65a44c7ebf4127328 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Thu, 8 Nov 2012 16:21:38 -0600 Subject: [PATCH 054/210] Fixing new version location --- extension/firefox/update.rdf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extension/firefox/update.rdf b/extension/firefox/update.rdf index d6b83700a..3bda6b207 100644 --- a/extension/firefox/update.rdf +++ b/extension/firefox/update.rdf @@ -15,7 +15,7 @@ 17.0 19.0a1 - https://github.com/mozilla/shumway/raw/gh-pages/extensions/firefox/shumway.xpi + https://github.com/mozilla/shumway/raw/gh-pages/extension/firefox/shumway.xpi From 73021178a69ca53048f6f27a73a3fbcbbbc45511 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Thu, 8 Nov 2012 18:00:08 -0600 Subject: [PATCH 055/210] Replacing window.print with console.log call --- examples/racing/avm2utils.js | 4 ++++ extension/firefox/content/web/avm2utils.js | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/examples/racing/avm2utils.js b/examples/racing/avm2utils.js index c00ebe66d..5e6a0a4bf 100644 --- a/examples/racing/avm2utils.js +++ b/examples/racing/avm2utils.js @@ -59,3 +59,7 @@ function createAVM2(builtinPath, libraryPath, sysMode, appMode, next) { } }); } + +window.print = function (msg) { + console.log(msg); +}; diff --git a/extension/firefox/content/web/avm2utils.js b/extension/firefox/content/web/avm2utils.js index c00ebe66d..5e6a0a4bf 100644 --- a/extension/firefox/content/web/avm2utils.js +++ b/extension/firefox/content/web/avm2utils.js @@ -59,3 +59,7 @@ function createAVM2(builtinPath, libraryPath, sysMode, appMode, next) { } }); } + +window.print = function (msg) { + console.log(msg); +}; From c9d3aa7c886ce536480827937f0a50eb9309ccbd Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Thu, 8 Nov 2012 18:26:05 -0600 Subject: [PATCH 056/210] Fix update id --- extension/firefox/update.rdf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extension/firefox/update.rdf b/extension/firefox/update.rdf index 3bda6b207..afbdc16c6 100644 --- a/extension/firefox/update.rdf +++ b/extension/firefox/update.rdf @@ -3,7 +3,7 @@ - + From 9672b280406dec9457248a60f3f235030d176263 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Thu, 8 Nov 2012 18:43:36 -0600 Subject: [PATCH 057/210] Autogenerate version number --- extension/firefox/Makefile | 8 +++++++- extension/firefox/install.rdf | 2 +- extension/firefox/update.rdf | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/extension/firefox/Makefile b/extension/firefox/Makefile index 7065658df..4bf747d51 100644 --- a/extension/firefox/Makefile +++ b/extension/firefox/Makefile @@ -1,9 +1,15 @@ # Just builds a ff extension +VERSION_BASELINE=c9d3aa7c886ce53648082 +VERSION=0.3.`git log --format=oneline $(VERSION_BASELINE)..|wc -l` + build: clean # Coping extension files + echo "Creating extension verions: $(VERSION)" mkdir build - cp -R ../../LICENSE components content bootstrap.js install.rdf update.rdf build/ + cp -R ../../LICENSE components content bootstrap.js build/ + sed s/\(SHUMWAY_VERSION\)/$(VERSION)/ install.rdf > build/install.rdf + sed s/\(SHUMWAY_VERSION\)/$(VERSION)/ update.rdf > build/update.rdf # Coping JavaScript content files mkdir build/content/swf cp ../../src/swf/*.js build/content/swf/ diff --git a/extension/firefox/install.rdf b/extension/firefox/install.rdf index 84b71fa23..7c10edb14 100644 --- a/extension/firefox/install.rdf +++ b/extension/firefox/install.rdf @@ -6,7 +6,7 @@ shumway@research.mozilla.org shumway - 0.2.6 + (SHUMWAY_VERSION) chrome://shumway/skin/logo.png diff --git a/extension/firefox/update.rdf b/extension/firefox/update.rdf index afbdc16c6..152c38fe0 100644 --- a/extension/firefox/update.rdf +++ b/extension/firefox/update.rdf @@ -8,7 +8,7 @@ - 0.2.6 + (SHUMWAY_VERSION) {ec8030f7-c20a-464f-9b0e-13a3a9e97384} From 9fb93c1ecd91e1a82134a7ba9c5309b0c785e073 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Fri, 9 Nov 2012 07:34:58 -0600 Subject: [PATCH 058/210] Always builds extension; list of the other examples --- Makefile | 6 ++++-- web/Makefile | 6 +++--- web/index.html | 10 +++++++++- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 7746e3990..ee3b8ac6b 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ default: @echo "run: make [check-system|install-utils|install-libs|build-tamarin-tests|" - @echo " build-playerglobal|build-extension|test|push-test|build-bot|start-build-bot]" + @echo " build-playerglobal|build-extension|build-web|" + @echo " test|push-test|build-bot|start-build-bot]" check-system: echo "Checking the presence of mercurial..." @@ -89,4 +90,5 @@ start-build-bot: sleep 60 ; \ done -.PHONY: check-system install-libs install-utils build-tamarin-tests build-playerglobal build-extension test +.PHONY: check-system install-libs install-utils build-tamarin-tests \ + build-playerglobal build-extension build-web test default diff --git a/web/Makefile b/web/Makefile index fa20d9895..ca4c3a6a3 100644 --- a/web/Makefile +++ b/web/Makefile @@ -4,7 +4,7 @@ SHUMWAY_ROOT=.. build: clean \ $(SHUMWAY_ROOT)/src/flash/playerGlobal.min.abc \ - $(SHUMWAY_ROOT)/extension/firefox/build/shumway.xpi + build-extension mkdir build cp -R $(SHUMWAY_ROOT)/LICENSE index.html build/ # Coping JavaScript content files @@ -59,7 +59,7 @@ build: clean \ echo "Success gh-pages is created. To push:" echo " cd web/build; git push -f git@github.com:mozilla/shumway.git gh-pages" -$(SHUMWAY_ROOT)/extension/firefox/build/shumway.xpi: +build-extension: $(MAKE) -C $(SHUMWAY_ROOT)/extension/firefox build $(SHUMWAY_ROOT)/src/flash/playerGlobal.min.abc: @@ -68,4 +68,4 @@ $(SHUMWAY_ROOT)/src/flash/playerGlobal.min.abc: clean: -rm -rf build -PHONY: build clean +PHONY: build clean build-extension diff --git a/web/index.html b/web/index.html index d5721163e..97a5a057d 100644 --- a/web/index.html +++ b/web/index.html @@ -50,7 +50,15 @@

Try it out!

Live demo lives here. Firefox extension lives here.

- +

Other examples: +

    +
  1. Tiger (AS3)
  2. +
  3. Racing (AS2) (as in live demo) + and Racing (AS3)
  4. +
  5. Pacman (AS2) + and Pacman (AS3)
  6. +
+

Download

You can download this project in either From d6d52914fb3b670d95a1e8f6400c4cbea129aa9a Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Fri, 9 Nov 2012 08:12:25 -0600 Subject: [PATCH 059/210] Fixes getting the object root --- src/flash/display/DisplayObject.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flash/display/DisplayObject.js b/src/flash/display/DisplayObject.js index 42cf8ac4c..c748a78a5 100644 --- a/src/flash/display/DisplayObject.js +++ b/src/flash/display/DisplayObject.js @@ -224,7 +224,7 @@ const DisplayObjectDefinition = (function () { return this._parent; }, get root() { - return this._root || (this._parent ? this._parent._root : null); + return this._root || (this._parent ? this._parent.root : null); }, get rotation() { return this._rotation; From c5c42514743c1fca0ae518b3fb5f76643230251d Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Fri, 9 Nov 2012 08:38:12 -0600 Subject: [PATCH 060/210] Fixes `range[2] is undefined` issue --- src/swf/font.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/swf/font.js b/src/swf/font.js index 9a1b1b0e2..f2e2e9108 100644 --- a/src/swf/font.js +++ b/src/swf/font.js @@ -18,6 +18,10 @@ function defineFont(tag, dictionary) { var glyphIndex = { }; var ranges = []; + var indices = []; + 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) @@ -30,7 +34,7 @@ function defineFont(tag, dictionary) { while (code = codes[i++]) { var start = code; var end = start; - var indices = [i - 1]; + indices.push(i - 1); while ((code = codes[i]) && end + 1 === code) { ++end; indices.push(i); @@ -130,7 +134,6 @@ function defineFont(tag, dictionary) { format314 ; - var glyphs = tag.glyphs; var glyf = '\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x31\x00'; var loca = '\x00\x00'; var resolution = tag.resolution || 1; @@ -282,7 +285,6 @@ function defineFont(tag, dictionary) { var advance = tag.advance; var resolution = tag.resolution || 1; - var glyphCount = glyphs.length; tables['hhea'] = '\x00\x01\x00\x00' + // version toString16(ascent) + // ascender From 958ca9f72a48ca0cced63e3fb318bd490c16508a Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Fri, 9 Nov 2012 09:21:10 -0600 Subject: [PATCH 061/210] Hack for goto to frame 0; fixes AS2 _framesloaded --- src/avm1/classes.js | 2 +- src/flash/display/MovieClip.js | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/avm1/classes.js b/src/avm1/classes.js index 6b221a5bb..6fbbeea6a 100644 --- a/src/avm1/classes.js +++ b/src/avm1/classes.js @@ -204,7 +204,7 @@ AS2MovieClip.prototype = Object.create({}, { enumerable: true }, _framesloaded: { // @flash.display.MovieClip - get: function get$_framesloaded() { return this.$nativeObject._framesloaded; }, + get: function get$_framesloaded() { return this.$nativeObject._framesLoaded; }, enumerable: true }, getBounds: { diff --git a/src/flash/display/MovieClip.js b/src/flash/display/MovieClip.js index 7f7a938b6..86eadfb61 100644 --- a/src/flash/display/MovieClip.js +++ b/src/flash/display/MovieClip.js @@ -50,6 +50,12 @@ const MovieClipDefinition = (function () { if (frameNum === this._currentFrame) return; + if (frameNum === 0) { + // HACK there is no data for this frame, but AS2 can jump to this frame index + this._currentFrame = 0; + return; + } + var children = this._children; var depthMap = this._depthMap; var framePromise = this._timeline[frameNum - 1]; From 576bd08c0d4901a26f721756aab61d6950c507e7 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Fri, 9 Nov 2012 10:02:03 -0600 Subject: [PATCH 062/210] Fixes font encoding --- src/swf/font.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/swf/font.js b/src/swf/font.js index f2e2e9108..1cb67f87a 100644 --- a/src/swf/font.js +++ b/src/swf/font.js @@ -18,7 +18,6 @@ function defineFont(tag, dictionary) { var glyphIndex = { }; var ranges = []; - var indices = []; var glyphs = tag.glyphs; var glyphCount = glyphs.length; @@ -34,7 +33,7 @@ function defineFont(tag, dictionary) { while (code = codes[i++]) { var start = code; var end = start; - indices.push(i - 1); + var indices = [i - 1]; while ((code = codes[i]) && end + 1 === code) { ++end; indices.push(i); @@ -43,13 +42,15 @@ function defineFont(tag, dictionary) { ranges.push([start, end, indices]); } } else { + var indices = []; + var UAC_OFFSET = 0xe000; for (var i = 0; i < glyphCount; i++) { - var code = 0xe000 + i; + var code = UAC_OFFSET + i; codes.push(code); glyphIndex[code] = i; indices.push(i); } - ranges.push([0, glyphCount - 1, indices]); + ranges.push([UAC_OFFSET, UAC_OFFSET + glyphCount - 1, indices]); } var ascent = tag.ascent || 1024; From 1acc6c73932a0bd76188fb9aa827af5a25bd8957 Mon Sep 17 00:00:00 2001 From: Tobias Schneider Date: Fri, 9 Nov 2012 19:19:12 +0100 Subject: [PATCH 063/210] Fix Promise.when. --- src/flash/util.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flash/util.js b/src/flash/util.js index 60795ab94..f8590e8df 100644 --- a/src/flash/util.js +++ b/src/flash/util.js @@ -45,7 +45,7 @@ Promise.when = function () { promise.resolve(); } else { var values = []; - for (var i = 0; i < numPromises; i++) { + for (var i = 0, n = numPromises; i < n; i++) { var arg = arguments[i]; arg.then(function (val) { values.push(val); From a48903d1b1a25be1e488962f858805aaf4301add Mon Sep 17 00:00:00 2001 From: Tobias Schneider Date: Fri, 9 Nov 2012 19:19:55 +0100 Subject: [PATCH 064/210] Fake sound support. --- src/flash/display/Loader.js | 10 ++++++++++ src/swf/tags.js | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/flash/display/Loader.js b/src/flash/display/Loader.js index 440e78034..36a28ac5f 100644 --- a/src/flash/display/Loader.js +++ b/src/flash/display/Loader.js @@ -77,6 +77,12 @@ const LoaderDefinition = (function () { case SWF_TAG_CODE_DEFINE_SHAPE4: symbol = defineShape(swfTag, symbols); break; + case SWF_TAG_CODE_DEFINE_SOUND: + symbol = { + type: 'sound', + id: swfTag.id + }; + break; case SWF_TAG_CODE_DEFINE_SPRITE: var depths = { }; var frame = { type: 'frame' }; @@ -561,6 +567,10 @@ const LoaderDefinition = (function () { graphics: graphics }; break; + case 'sound': + symbolInfo.className = 'flash.media.Sound'; + symbolInfo.props = { }; + break; case 'sprite': var frameCount = symbol.frameCount; var frameLabels = { }; diff --git a/src/swf/tags.js b/src/swf/tags.js index 6a88eff7f..5120c2b4f 100644 --- a/src/swf/tags.js +++ b/src/swf/tags.js @@ -328,6 +328,6 @@ var FRAME_LABEL = { var DEFINE_SOUND = { id: UI16, $$soundFlags: UI8, - samplesCound: UI32, + samplesCount: UI32, soundData: BINARY(0) }; From cf0d228ba802a2d0a187460ae93756a8c5c54570 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Fri, 9 Nov 2012 12:35:45 -0600 Subject: [PATCH 065/210] Stubs SoundClass for AS3 --- examples/inspector/inspector.html | 1 + examples/racing/index.html | 1 + extension/firefox/content/web/viewer.html | 1 + src/flash/media/Sound.js | 15 +++++++++++++++ src/flash/stubs.js | 3 ++- 5 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 src/flash/media/Sound.js diff --git a/examples/inspector/inspector.html b/examples/inspector/inspector.html index ea35f87b5..2e9da45f4 100644 --- a/examples/inspector/inspector.html +++ b/examples/inspector/inspector.html @@ -120,6 +120,7 @@ + + + + + + + + + + + + From 7d06e66e7a16d571b6548d0b1b821030a29c18d3 Mon Sep 17 00:00:00 2001 From: Michael Bebenita Date: Fri, 9 Nov 2012 15:15:00 -0800 Subject: [PATCH 075/210] Update name and description. --- extension/firefox/install.rdf | 2 +- web/index.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extension/firefox/install.rdf b/extension/firefox/install.rdf index c09a716b8..d4513af35 100644 --- a/extension/firefox/install.rdf +++ b/extension/firefox/install.rdf @@ -30,7 +30,7 @@ true true Mozilla Research - Shumway loader + Shumway is an HTML5 technology experiment that explores building a faithful and efficient renderer for the SWF file format without native code assistance. https://github.com/mozilla/shumway/ 2 diff --git a/web/index.html b/web/index.html index 6ae2a61fa..8f5a55d95 100644 --- a/web/index.html +++ b/web/index.html @@ -42,7 +42,7 @@

-

shumway

+

Shumway

Shumway is an HTML5 technology experiment that explores building a faithful and efficient renderer for the SWF file format without native code assistance. From 43f206ba4308aaff637e5100f7dba099264b2429 Mon Sep 17 00:00:00 2001 From: Michael Bebenita Date: Fri, 9 Nov 2012 16:05:21 -0800 Subject: [PATCH 076/210] Give inspector default settings. --- examples/inspector/inspectorSettings.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/examples/inspector/inspectorSettings.js b/examples/inspector/inspectorSettings.js index 38bfb5610..1d236c78d 100644 --- a/examples/inspector/inspectorSettings.js +++ b/examples/inspector/inspectorSettings.js @@ -1,5 +1,11 @@ function loadState() { - return localStorage["Inspector-Settings"] ? JSON.parse(localStorage["Inspector-Settings"]): {}; + return localStorage["Inspector-Settings"] ? JSON.parse(localStorage["Inspector-Settings"]) : { + compiler: true, + verifier: true, + optimizer: true, + inlineCaching: true, + release: true + }; } function saveState(state) { From d0856aef8265a104388b1e1c50bbf7072bfa6f46 Mon Sep 17 00:00:00 2001 From: Michael Bebenita Date: Fri, 9 Nov 2012 16:41:28 -0800 Subject: [PATCH 077/210] Update webpage. --- web/Makefile | 2 +- web/images/mozilla.png | Bin 0 -> 4435 bytes web/index.html | 55 ++++++++++++++++------------------------- 3 files changed, 22 insertions(+), 35 deletions(-) create mode 100644 web/images/mozilla.png diff --git a/web/Makefile b/web/Makefile index 8b899affd..0ace429b3 100644 --- a/web/Makefile +++ b/web/Makefile @@ -6,7 +6,7 @@ build: clean \ $(SHUMWAY_ROOT)/src/flash/playerGlobal.min.abc \ build-extension mkdir build - cp -R $(SHUMWAY_ROOT)/LICENSE index.html build/ + cp -R $(SHUMWAY_ROOT)/LICENSE index.html images build/ # Coping JavaScript content files mkdir build/src mkdir build/src/swf diff --git a/web/images/mozilla.png b/web/images/mozilla.png new file mode 100644 index 0000000000000000000000000000000000000000..cc4bc7c73a8188d699ef7199b0f0e382ebcbe5d3 GIT binary patch literal 4435 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 literal 0 HcmV?d00001 diff --git a/web/index.html b/web/index.html index 8f5a55d95..bdf0011da 100644 --- a/web/index.html +++ b/web/index.html @@ -7,22 +7,23 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + diff --git a/test/harness/slave.js b/test/harness/slave.js new file mode 100644 index 000000000..39d13b075 --- /dev/null +++ b/test/harness/slave.js @@ -0,0 +1,81 @@ +function loadMovie(path) { + createAVM2(builtinPath, playerGlobalPath, EXECUTION_MODE.INTERPRET, EXECUTION_MODE.COMPILE, function (avm2) { + function loaded() { sendResponse(); } + + new BinaryFileReader(path).readAll(null, function(buffer) { + if (!buffer) { + throw "Unable to open the file " + SWF_PATH + ": " + error; + } + SWF.embed(buffer, document.getElementById("stage"), { onComplete: loaded }); + }); + }); +} + +var traceMessages = ''; +natives.print = function() { + return function(s) { + traceMessages += s + '\n'; + }; +}; + +function sendResponse(data) { + window.parent.postMessage({ + type: 'test-response', + result: data + }, '*'); +} + +function getCanvasData() { + var canvas = document.getElementsByTagName('canvas')[0]; + return canvas.getDataURL('image/png'); +} + +var mouseOutside = true; + +function sendMouseEvent(type, x, y) { + var isMouseMove = type == 'mousemove'; + var canvas = document.getElementsByTagName('canvas')[0]; + var e = document.createEvent('MouseEvents'); + e.initMouseEvent(type, true, !isMouseMove, + document.defaultView, isMouseMove ? 0 : 1, + x, y, x, y, + false, false, false, false, 0, canvas); + canvas.dispatchEvent(e); +} + +window.addEventListener('message', function (e) { + var data = e.data; + if (typeof data !== 'object' || data.type !== 'test-message') + return; + switch (data.topic) { + case 'load': + loadMovie(data.path); + break; + case 'advance': + var delay = data.args[0]; + setTimeout(function () { + sendResponse(); + }, delay); + break; + case 'mouse-move': + if (mouseOutside) { + sendMouseEvent('mouseover', data.args[0], data.args[1]); + mouseOutside = false; + } + sendMouseEvent('mousemove', data.args[0], data.args[1]); + break; + case 'mouse-press': + sendMouseEvent('mousedown', data.args[0], data.args[1]); + sendMouseEvent('click', data.args[0], data.args[1]); + break; + case 'mouse-release': + sendMouseEvent('mouseup', data.args[0], data.args[1]); + break; + case 'get-trace': + sendResponse(traceMessages); + break; + case 'get-image': + sendResponse(getCanvasData()); + break; + } +}); \ No newline at end of file diff --git a/test/harness/testutils.js b/test/harness/testutils.js new file mode 100644 index 000000000..d16d72757 --- /dev/null +++ b/test/harness/testutils.js @@ -0,0 +1,272 @@ +function Test() {} +Test.prototype = { + advance: function(delay) { + TestContext.enqueue('advance', [delay], NullMessageSink); + }, + mouse_move: function(x, y) { + TestContext.enqueue('mouse-move', [x, y]); + }, + mouse_press: function(x, y) { + TestContext.enqueue('mouse-press', [x, y]); + }, + mouse_release: function(x, y) { + TestContext.enqueue('mouse-release', [x, y]); + }, + render: function() { + var image = new Image(); + TestContext.enqueue('get-image', null, image); + return image; + }, + reset: function(file) { + TestContext.reset(file); + }, + get rate() { return 1; }, // assume all rates 1 -- some of the tests might not works + get quit() { throw 'not impl'; }, + get trace() { + var buffer = new Buffer(); + TestContext.enqueue('get-trace', null, buffer); + return buffer; + }, + get launched() { throw 'not impl'; }, +}; + +function Buffer() { + this.loaded = new Promise; +} +Buffer.load = function(path) { + var buffer = new Buffer(); + var xhr = new XMLHttpRequest(); + xhr.open("GET", path, true); + xhr.onreadystatechange = function(event) { + if (xhr.readyState === 4) { + buffer.s = xhr.responseText; + buffer.loaded.resolve(); + } + } + xhr.setRequestHeader("If-Modified-Since", "Fri, 01 Jan 1960 00:00:00 GMT"); // no-cache + xhr.send(null); + return buffer; +} +Buffer.prototype = { + _message: function (s) { + this.s = s; + this.loaded.resolve(); + }, + diff: function(buffer) { + Promise.when(this.loaded, buffer.loaded).then(function() { + TestContext.compareTextResults(this.s, buffer.s); + }.bind(this)); + }, + find: function() { throw 'not impl'; }, + sub: function() { throw 'not impl'; }, + toString: function() { throw 'not impl'; } +}; + +function Image(path) { + this.loaded = new Promise; + this.img = document.createElement('img'); + this.img.onload = function() { + this.loaded.resolve(); + }; + if (path) + this.img.src = path; +} +Image.prototype = { + _message: function (data) { + this.img.src = data; + }, + save: function() {}, + compare: function(image) { + Promise.when(this.loaded, image.loaded).then(function() { + TextContext.compareImageResults(this.img, image.img); + }.bind(this)); + } +}; + +function Socket() {throw 'not impl'; } +Socket.prototype = { + close: function() {throw 'not impl'; }, + error: function() {throw 'not impl'; }, + send: function() {throw 'not impl'; }, + get closed() { return false; } +}; + +var verbose = false; + +var print = function (s) { + if (verbose && s) + console.log ("INFO: " + s); +}; + +var error = function (s) { + if (verbose && s) + console.error ("ERROR: " + s); +}; + +function Native() {} +Native.print = print; + +function execStas(path, filenames) { + function complete() { + TestContext._resultPromise.then(function (result) { + resultPromise.resolve(result); + }); + } + function exec(code) { + var jsCode = "var run_test, fail;\n" + code; + var fn = new Function('filenames', jsCode); + fn(filenames); + complete(); + } + function load() { + var xhr = new XMLHttpRequest(); + xhr.open("GET", path, true); + xhr.onreadystatechange = function(event) { + if (xhr.readyState === 4) { + if (xhr.status !== 200 && xhr.status !== 0) { + complete(null, xhr.statusText); + return; + } + exec(xhr.responseText); + } + } + xhr.setRequestHeader("If-Modified-Since", "Fri, 01 Jan 1960 00:00:00 GMT"); // no-cache + xhr.send(null); + } + var resultPromise = new Promise; + load(); + return resultPromise; +} + +function Promise() { + this.resolved = false; + this._callbacks = []; +} +Promise.when = function () { + var numPromises = arguments.length; + var promise = new Promise; + if (!numPromises) { + promise.resolve(); + } else { + var values = []; + for (var i = 0, n = numPromises; i < n; i++) { + var arg = arguments[i]; + arg.then(function (val) { + values.push(val); + if (!--numPromises) + promise.resolve.apply(promise, values); + }); + } + } + return promise; +}; +Promise.prototype.resolve = function (val) { + if (this.resolved) + return; + + this.resolved = true; + this.value = val; + + var callbacks = this._callbacks; + for (var i = 0, n = callbacks.length; i < n; i++) { + var cb = callbacks[i]; + cb(val); + } +}; +Promise.prototype.then = function (cb) { + if (this.resolved) + cb(this.value); + else + this._callbacks.push(cb); +}; + +var TestContext = { + enqueue: function(msg, args, respondTo) { + var promise = new Promise; + TestContext._previousPromise.then(function () { + TestContext._currentPromise = promise; + TestContext._driverWindow.postMessage({ + type: 'test-message', + topic: msg, + args: args + }, '*'); + if (respondTo) { + var responsePromise = new Promise; + TestContext._responsePromise = responsePromise; + responsePromise.then(function (s) { + respondTo._message(s); + promise.resolve(); + }); + } else { + promise.resolve(); + } + }); + TestContext._previousPromise = promise; + }, + compareTextResults: function (actual, expected) { + var result; + if (actual == expected) { + TestContext.log('SUCCESS'); + result = {failure: false}; + } else { + TestContext.log('FAILED: ' + actual + ' !== ' + expected); + result = {failure: true, type: 'text', data1: actual, data2: expected}; + } + TestContext._currentResultPromise.resolve(result); + }, + compareImageResults: function (actual, expected) { + throw 'not impl'; + }, + _id: Date.now, + _driverWindow: null, + _resultPromise: new Promise, + _currentResultPromise: null, + _currentPromise: null, + _previousPromise: new Promise, + _responsePromise: null, + reset: function (file) { + var promise = new Promise; + TestContext._previousPromise.then(function () { + TestContext._currentPromise = promise; + }); + TestContext._previousPromise = promise; + + var resultPromise = new Promise; + TestContext._resultPromise.then(function () { + TestContext.log('Testing ' + file + '...'); + TestContext._currentResultPromise = resultPromise; + + var id = TestContext._id++; + var movieFrame = document.getElementById('movie') + movieFrame.addEventListener('load', function frameLoad() { + movieFrame.removeEventListener('load', frameLoad); + var movie = movieFrame.contentWindow; + TestContext._driverWindow = movie; + TestContext._responsePromise = promise; + movie.postMessage({ + type: 'test-message', + topic: 'load', + path: file.indexOf(':') >= 0 || file[0] === '/' ? file : '../' + file + }, '*'); + }); + movieFrame.src = 'harness/slave.html?n=' + id; + }); + TestContext._resultPromise = resultPromise; + }, + log: function (s) { + console.log('TEST: ' + s); + } +}; +TestContext._previousPromise.resolve(); +TestContext._resultPromise.resolve(); + +var NullMessageSink = { + _message: function() {} +}; + +window.addEventListener('message', function (e) { + var data = e.data; + if (typeof data !== 'object' || data.type !== 'test-response') + return; + TestContext._responsePromise.resolve(data.result); +}); diff --git a/test/resources/browser_manifests/.gitignore b/test/resources/browser_manifests/.gitignore new file mode 100644 index 000000000..ca57ac505 --- /dev/null +++ b/test/resources/browser_manifests/.gitignore @@ -0,0 +1,2 @@ +browser_manifest.json + diff --git a/test/resources/browser_manifests/browser_manifest.json.linux b/test/resources/browser_manifests/browser_manifest.json.linux new file mode 100644 index 000000000..a576899b5 --- /dev/null +++ b/test/resources/browser_manifests/browser_manifest.json.linux @@ -0,0 +1,10 @@ +[ + { + "name":"firefox7", + "path":"/home/sayrer/firefoxen/nightly/firefox" + }, + { + "name":"chrome14", + "path":"/opt/google/chrome/chrome" + } +] diff --git a/test/resources/browser_manifests/browser_manifest.json.mac b/test/resources/browser_manifests/browser_manifest.json.mac new file mode 100644 index 000000000..5b93ff196 --- /dev/null +++ b/test/resources/browser_manifests/browser_manifest.json.mac @@ -0,0 +1,14 @@ +[ + { + "name":"firefox5", + "path":"/Applications/Firefox.app" + }, + { + "name":"firefox6", + "path":"/Users/sayrer/firefoxen/Aurora.app" + }, + { + "name":"chrome14", + "path":"/Applications/Google Chrome.app" + } +] diff --git a/test/resources/browser_manifests/browser_manifest.json.windows b/test/resources/browser_manifests/browser_manifest.json.windows new file mode 100644 index 000000000..a19727b05 --- /dev/null +++ b/test/resources/browser_manifests/browser_manifest.json.windows @@ -0,0 +1,10 @@ +[ + { + "name":"firefox", + "path":"C:/Program Files (x86)/Firefox/firefox.exe" + }, + { + "name":"aurora", + "path":"C:/Program Files (x86)/Aurora/firefox.exe" + } +] diff --git a/test/resources/favicon.ico b/test/resources/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..d44438903b751f4732f5365783eb0229b0501f9a GIT binary patch literal 1406 zcmZvcze^lJ6vy9y;f`fV)+?@Ze|W?Y>#3{^YAe`S+YM=~Z34NW`?g{0%{Gm#-zuW37pASug&9hEW%I5<8GkmQYMp$Ony#e@#BjuEiFmE-c}V zrd^0bcjyk?p*!@r%%gjB&%~p9bOs6N0X?7xgn+KhmAQuGZ0RljmPD3CR#cKborS@| zU}3N@BqSIt3>F3pgM}es!eC*rFjyEY3<(_u3xkEh!eC*riUx;;!$uC(Q~?ymczRl( zp~pvt#bNF+awK)Iq%v^Rap7Qbu%xoU;oxv^I5->}sZ?+{7#s`^hFCfWhl9bv5b#p^ zR6=~ZlX)s{tPWIod!kaQ@%AuzOg#o3CXcu0rYDKV+vAsduroh z@GyAl5Vwu0q^Cz=q>tN34FY}vwg5-KFKun)paubs5IK0TwB0NUumo5F5COyV3cwOr z7zhdo0TzBV@~|fXmJsWaSmN6dcL5Csg+XCZ7!(GDA-zs81Q-+sg(1K|8XEC1C=3dN z!a!;oIt&Vf!k_>s{()r5LM6zN!!dVoXv!U9oUF=cIXF0wqoX4^K0cO{lM^{VKbNz! zGr7FHl<9OTS65eZb8{oNx3_YCe=mzaDxXeI`5%v|Zu}3#fqZEe^Tw%4_Mf9?On&&F zi}beZwkZd!>yBC3w&vx-=SH%5uQV+Iv+k~DdEGL9UJhoPqdUoZxoMl$(3xtsdZBU89L3N8 literal 0 HcmV?d00001 diff --git a/test/resources/firefox/extensions/special-powers@mozilla.org/chrome.manifest b/test/resources/firefox/extensions/special-powers@mozilla.org/chrome.manifest new file mode 100644 index 000000000..614f31c3a --- /dev/null +++ b/test/resources/firefox/extensions/special-powers@mozilla.org/chrome.manifest @@ -0,0 +1,4 @@ +content specialpowers chrome/specialpowers/content/ +component {59a52458-13e0-4d93-9d85-a637344f29a1} components/SpecialPowersObserver.js +contract @mozilla.org/special-powers-observer;1 {59a52458-13e0-4d93-9d85-a637344f29a1} +category profile-after-change @mozilla.org/special-powers-observer;1 @mozilla.org/special-powers-observer;1 diff --git a/test/resources/firefox/extensions/special-powers@mozilla.org/chrome/specialpowers/content/specialpowers.js b/test/resources/firefox/extensions/special-powers@mozilla.org/chrome/specialpowers/content/specialpowers.js new file mode 100644 index 000000000..538b104eb --- /dev/null +++ b/test/resources/firefox/extensions/special-powers@mozilla.org/chrome/specialpowers/content/specialpowers.js @@ -0,0 +1,372 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Special Powers code + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Clint Talbert cmtalbert@gmail.com + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK *****/ +/* This code is loaded in every child process that is started by mochitest in + * order to be used as a replacement for UniversalXPConnect + */ + +var Ci = Components.interfaces; +var Cc = Components.classes; + +function SpecialPowers(window) { + this.window = window; + bindDOMWindowUtils(this, window); + this._encounteredCrashDumpFiles = []; + this._unexpectedCrashDumpFiles = { }; + this._crashDumpDir = null; + this._pongHandlers = []; + this._messageListener = this._messageReceived.bind(this); + addMessageListener("SPPingService", this._messageListener); +} + +function bindDOMWindowUtils(sp, window) { + var util = window.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + // This bit of magic brought to you by the letters + // B Z, and E, S and the number 5. + // + // Take all of the properties on the nsIDOMWindowUtils-implementing + // object, and rebind them onto a new object with a stub that uses + // apply to call them from this privileged scope. This way we don't + // have to explicitly stub out new methods that appear on + // nsIDOMWindowUtils. + var proto = Object.getPrototypeOf(util); + var target = {}; + function rebind(desc, prop) { + if (prop in desc && typeof(desc[prop]) == "function") { + var oldval = desc[prop]; + desc[prop] = function() { return oldval.apply(util, arguments); }; + } + } + for (var i in proto) { + var desc = Object.getOwnPropertyDescriptor(proto, i); + rebind(desc, "get"); + rebind(desc, "set"); + rebind(desc, "value"); + Object.defineProperty(target, i, desc); + } + sp.DOMWindowUtils = target; +} + +SpecialPowers.prototype = { + toString: function() { return "[SpecialPowers]"; }, + sanityCheck: function() { return "foo"; }, + + // This gets filled in in the constructor. + DOMWindowUtils: undefined, + + // Mimic the get*Pref API + getBoolPref: function(aPrefName) { + return (this._getPref(aPrefName, 'BOOL')); + }, + getIntPref: function(aPrefName) { + return (this._getPref(aPrefName, 'INT')); + }, + getCharPref: function(aPrefName) { + return (this._getPref(aPrefName, 'CHAR')); + }, + getComplexValue: function(aPrefName, aIid) { + return (this._getPref(aPrefName, 'COMPLEX', aIid)); + }, + + // Mimic the set*Pref API + setBoolPref: function(aPrefName, aValue) { + return (this._setPref(aPrefName, 'BOOL', aValue)); + }, + setIntPref: function(aPrefName, aValue) { + return (this._setPref(aPrefName, 'INT', aValue)); + }, + setCharPref: function(aPrefName, aValue) { + return (this._setPref(aPrefName, 'CHAR', aValue)); + }, + setComplexValue: function(aPrefName, aIid, aValue) { + return (this._setPref(aPrefName, 'COMPLEX', aValue, aIid)); + }, + + // Mimic the clearUserPref API + clearUserPref: function(aPrefName) { + var msg = {'op':'clear', 'prefName': aPrefName, 'prefType': ""}; + sendSyncMessage('SPPrefService', msg); + }, + + // Private pref functions to communicate to chrome + _getPref: function(aPrefName, aPrefType, aIid) { + var msg = {}; + if (aIid) { + // Overloading prefValue to handle complex prefs + msg = {'op':'get', 'prefName': aPrefName, 'prefType':aPrefType, 'prefValue':[aIid]}; + } else { + msg = {'op':'get', 'prefName': aPrefName,'prefType': aPrefType}; + } + return(sendSyncMessage('SPPrefService', msg)[0]); + }, + _setPref: function(aPrefName, aPrefType, aValue, aIid) { + var msg = {}; + if (aIid) { + msg = {'op':'set','prefName':aPrefName, 'prefType': aPrefType, 'prefValue': [aIid,aValue]}; + } else { + msg = {'op':'set', 'prefName': aPrefName, 'prefType': aPrefType, 'prefValue': aValue}; + } + return(sendSyncMessage('SPPrefService', msg)[0]); + }, + + //XXX: these APIs really ought to be removed, they're not e10s-safe. + // (also they're pretty Firefox-specific) + _getTopChromeWindow: function(window) { + return window.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShellTreeItem) + .rootTreeItem + .QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindow) + .QueryInterface(Ci.nsIDOMChromeWindow); + }, + _getDocShell: function(window) { + return window.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShell); + }, + _getMUDV: function(window) { + return this._getDocShell(window).contentViewer + .QueryInterface(Ci.nsIMarkupDocumentViewer); + }, + _getAutoCompletePopup: function(window) { + return this._getTopChromeWindow(window).document + .getElementById("PopupAutoComplete"); + }, + addAutoCompletePopupEventListener: function(window, listener) { + this._getAutoCompletePopup(window).addEventListener("popupshowing", + listener, + false); + }, + removeAutoCompletePopupEventListener: function(window, listener) { + this._getAutoCompletePopup(window).removeEventListener("popupshowing", + listener, + false); + }, + isBackButtonEnabled: function(window) { + return !this._getTopChromeWindow(window).document + .getElementById("Browser:Back") + .hasAttribute("disabled"); + }, + + addChromeEventListener: function(type, listener, capture, allowUntrusted) { + addEventListener(type, listener, capture, allowUntrusted); + }, + removeChromeEventListener: function(type, listener, capture) { + removeEventListener(type, listener, capture); + }, + + getFullZoom: function(window) { + return this._getMUDV(window).fullZoom; + }, + setFullZoom: function(window, zoom) { + this._getMUDV(window).fullZoom = zoom; + }, + getTextZoom: function(window) { + return this._getMUDV(window).textZoom; + }, + setTextZoom: function(window, zoom) { + this._getMUDV(window).textZoom = zoom; + }, + + createSystemXHR: function() { + return Cc["@mozilla.org/xmlextras/xmlhttprequest;1"] + .createInstance(Ci.nsIXMLHttpRequest); + }, + + gc: function() { + this.DOMWindowUtils.garbageCollect(); + }, + + hasContentProcesses: function() { + try { + var rt = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime); + return rt.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT; + } catch (e) { + return true; + } + }, + + registerProcessCrashObservers: function() { + addMessageListener("SPProcessCrashService", this._messageListener); + sendSyncMessage("SPProcessCrashService", { op: "register-observer" }); + }, + + _messageReceived: function(aMessage) { + switch (aMessage.name) { + case "SPProcessCrashService": + if (aMessage.json.type == "crash-observed") { + var self = this; + aMessage.json.dumpIDs.forEach(function(id) { + self._encounteredCrashDumpFiles.push(id + ".dmp"); + self._encounteredCrashDumpFiles.push(id + ".extra"); + }); + } + break; + + case "SPPingService": + if (aMessage.json.op == "pong") { + var handler = this._pongHandlers.shift(); + if (handler) { + handler(); + } + } + break; + } + return true; + }, + + removeExpectedCrashDumpFiles: function(aExpectingProcessCrash) { + var success = true; + if (aExpectingProcessCrash) { + var message = { + op: "delete-crash-dump-files", + filenames: this._encounteredCrashDumpFiles + }; + if (!sendSyncMessage("SPProcessCrashService", message)[0]) { + success = false; + } + } + this._encounteredCrashDumpFiles.length = 0; + return success; + }, + + findUnexpectedCrashDumpFiles: function() { + var self = this; + var message = { + op: "find-crash-dump-files", + crashDumpFilesToIgnore: this._unexpectedCrashDumpFiles + }; + var crashDumpFiles = sendSyncMessage("SPProcessCrashService", message)[0]; + crashDumpFiles.forEach(function(aFilename) { + self._unexpectedCrashDumpFiles[aFilename] = true; + }); + return crashDumpFiles; + }, + + executeAfterFlushingMessageQueue: function(aCallback) { + this._pongHandlers.push(aCallback); + sendAsyncMessage("SPPingService", { op: "ping" }); + }, + + executeSoon: function(aFunc) { + var tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager); + tm.mainThread.dispatch({ + run: function() { + aFunc(); + } + }, Ci.nsIThread.DISPATCH_NORMAL); + }, + + /* from http://mxr.mozilla.org/mozilla-central/source/testing/mochitest/tests/SimpleTest/quit.js + * by Bob Clary, Jeff Walden, and Robert Sayre. + */ + quitApplication: function() { + function canQuitApplication() + { + var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); + if (!os) + return true; + + try { + var cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool); + os.notifyObservers(cancelQuit, "quit-application-requested", null); + + // Something aborted the quit process. + if (cancelQuit.data) + return false; + } catch (ex) {} + return true; + } + + if (!canQuitApplication()) + return false; + + var appService = Cc['@mozilla.org/toolkit/app-startup;1'].getService(Ci.nsIAppStartup); + appService.quit(Ci.nsIAppStartup.eForceQuit); + return true; + } +}; + +// Expose everything but internal APIs (starting with underscores) to +// web content. +SpecialPowers.prototype.__exposedProps__ = {}; +for each (i in Object.keys(SpecialPowers.prototype).filter(function(v) {return v.charAt(0) != "_";})) { + SpecialPowers.prototype.__exposedProps__[i] = "r"; +} + +// Attach our API to the window. +function attachSpecialPowersToWindow(aWindow) { + try { + if ((aWindow !== null) && + (aWindow !== undefined) && + (aWindow.wrappedJSObject) && + !(aWindow.wrappedJSObject.SpecialPowers)) { + aWindow.wrappedJSObject.SpecialPowers = new SpecialPowers(aWindow); + } + } catch(ex) { + dump("TEST-INFO | specialpowers.js | Failed to attach specialpowers to window exception: " + ex + "\n"); + } +} + +// This is a frame script, so it may be running in a content process. +// In any event, it is targeted at a specific "tab", so we listen for +// the DOMWindowCreated event to be notified about content windows +// being created in this context. + +function SpecialPowersManager() { + addEventListener("DOMWindowCreated", this, false); +} + +SpecialPowersManager.prototype = { + handleEvent: function handleEvent(aEvent) { + var window = aEvent.target.defaultView; + + // Need to make sure we are called on what we care about - + // content windows. DOMWindowCreated is called on *all* HTMLDocuments, + // some of which belong to chrome windows or other special content. + // + var uri = window.document.documentURIObject; + if (uri.scheme === "chrome" || uri.spec.split(":")[0] == "about") { + return; + } + + attachSpecialPowersToWindow(window); + } +}; + +var specialpowersmanager = new SpecialPowersManager(); diff --git a/test/resources/firefox/extensions/special-powers@mozilla.org/components/SpecialPowersObserver.js b/test/resources/firefox/extensions/special-powers@mozilla.org/components/SpecialPowersObserver.js new file mode 100644 index 000000000..90655e2e7 --- /dev/null +++ b/test/resources/firefox/extensions/special-powers@mozilla.org/components/SpecialPowersObserver.js @@ -0,0 +1,293 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Special Powers code + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Jesse Ruderman + * Robert Sayre + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK *****/ + +// Based on: +// https://bugzilla.mozilla.org/show_bug.cgi?id=549539 +// https://bug549539.bugzilla.mozilla.org/attachment.cgi?id=429661 +// https://developer.mozilla.org/en/XPCOM/XPCOM_changes_in_Gecko_1.9.3 +// http://mxr.mozilla.org/mozilla-central/source/toolkit/components/console/hudservice/HUDService.jsm#3240 +// https://developer.mozilla.org/en/how_to_build_an_xpcom_component_in_javascript + +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); +Components.utils.import("resource://gre/modules/Services.jsm"); + +const Cc = Components.classes; +const Ci = Components.interfaces; + +const CHILD_SCRIPT = "chrome://specialpowers/content/specialpowers.js" + +/** + * Special Powers Exception - used to throw exceptions nicely + **/ +function SpecialPowersException(aMsg) { + this.message = aMsg; + this.name = "SpecialPowersException"; +} + +SpecialPowersException.prototype.toString = function() { + return this.name + ': "' + this.message + '"'; +}; + +/* XPCOM gunk */ +function SpecialPowersObserver() { + this._isFrameScriptLoaded = false; + this._messageManager = Cc["@mozilla.org/globalmessagemanager;1"]. + getService(Ci.nsIChromeFrameMessageManager); +} + +SpecialPowersObserver.prototype = { + classDescription: "Special powers Observer for use in testing.", + classID: Components.ID("{59a52458-13e0-4d93-9d85-a637344f29a1}"), + contractID: "@mozilla.org/special-powers-observer;1", + QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIObserver]), + _xpcom_categories: [{category: "profile-after-change", service: true }], + + observe: function(aSubject, aTopic, aData) + { + switch (aTopic) { + case "profile-after-change": + this.init(); + break; + + case "chrome-document-global-created": + if (!this._isFrameScriptLoaded) { + // Register for any messages our API needs us to handle + this._messageManager.addMessageListener("SPPrefService", this); + this._messageManager.addMessageListener("SPProcessCrashService", this); + this._messageManager.addMessageListener("SPPingService", this); + + this._messageManager.loadFrameScript(CHILD_SCRIPT, true); + this._isFrameScriptLoaded = true; + } + break; + + case "xpcom-shutdown": + this.uninit(); + break; + + case "plugin-crashed": + case "ipc:content-shutdown": + function addDumpIDToMessage(propertyName) { + var id = aSubject.getPropertyAsAString(propertyName); + if (id) { + message.dumpIDs.push(id); + } + } + + var message = { type: "crash-observed", dumpIDs: [] }; + aSubject = aSubject.QueryInterface(Ci.nsIPropertyBag2); + if (aTopic == "plugin-crashed") { + addDumpIDToMessage("pluginDumpID"); + addDumpIDToMessage("browserDumpID"); + } else { // ipc:content-shutdown + addDumpIDToMessage("dumpID"); + } + this._messageManager.sendAsyncMessage("SPProcessCrashService", message); + break; + } + }, + + init: function() + { + var obs = Services.obs; + obs.addObserver(this, "xpcom-shutdown", false); + obs.addObserver(this, "chrome-document-global-created", false); + }, + + uninit: function() + { + var obs = Services.obs; + obs.removeObserver(this, "chrome-document-global-created", false); + this.removeProcessCrashObservers(); + }, + + addProcessCrashObservers: function() { + if (this._processCrashObserversRegistered) { + return; + } + + Services.obs.addObserver(this, "plugin-crashed", false); + Services.obs.addObserver(this, "ipc:content-shutdown", false); + this._processCrashObserversRegistered = true; + }, + + removeProcessCrashObservers: function() { + if (!this._processCrashObserversRegistered) { + return; + } + + Services.obs.removeObserver(this, "plugin-crashed"); + Services.obs.removeObserver(this, "ipc:content-shutdown"); + this._processCrashObserversRegistered = false; + }, + + getCrashDumpDir: function() { + if (!this._crashDumpDir) { + var directoryService = Cc["@mozilla.org/file/directory_service;1"] + .getService(Ci.nsIProperties); + this._crashDumpDir = directoryService.get("ProfD", Ci.nsIFile); + this._crashDumpDir.append("minidumps"); + } + return this._crashDumpDir; + }, + + deleteCrashDumpFiles: function(aFilenames) { + var crashDumpDir = this.getCrashDumpDir(); + if (!crashDumpDir.exists()) { + return false; + } + + var success = aFilenames.length != 0; + aFilenames.forEach(function(crashFilename) { + var file = crashDumpDir.clone(); + file.append(crashFilename); + if (file.exists()) { + file.remove(false); + } else { + success = false; + } + }); + return success; + }, + + findCrashDumpFiles: function(aToIgnore) { + var crashDumpDir = this.getCrashDumpDir(); + var entries = crashDumpDir.exists() && crashDumpDir.directoryEntries; + if (!entries) { + return []; + } + + var crashDumpFiles = []; + while (entries.hasMoreElements()) { + var file = entries.getNext().QueryInterface(Ci.nsIFile); + var path = String(file.path); + if (path.match(/\.(dmp|extra)$/) && !aToIgnore[path]) { + crashDumpFiles.push(path); + } + } + return crashDumpFiles.concat(); + }, + + /** + * messageManager callback function + * This will get requests from our API in the window and process them in chrome for it + **/ + receiveMessage: function(aMessage) { + switch(aMessage.name) { + case "SPPrefService": + var prefs = Services.prefs; + var prefType = aMessage.json.prefType.toUpperCase(); + var prefName = aMessage.json.prefName; + var prefValue = "prefValue" in aMessage.json ? aMessage.json.prefValue : null; + + if (aMessage.json.op == "get") { + if (!prefName || !prefType) + throw new SpecialPowersException("Invalid parameters for get in SPPrefService"); + } else if (aMessage.json.op == "set") { + if (!prefName || !prefType || prefValue === null) + throw new SpecialPowersException("Invalid parameters for set in SPPrefService"); + } else if (aMessage.json.op == "clear") { + if (!prefName) + throw new SpecialPowersException("Invalid parameters for clear in SPPrefService"); + } else { + throw new SpecialPowersException("Invalid operation for SPPrefService"); + } + // Now we make the call + switch(prefType) { + case "BOOL": + if (aMessage.json.op == "get") + return(prefs.getBoolPref(prefName)); + else + return(prefs.setBoolPref(prefName, prefValue)); + case "INT": + if (aMessage.json.op == "get") + return(prefs.getIntPref(prefName)); + else + return(prefs.setIntPref(prefName, prefValue)); + case "CHAR": + if (aMessage.json.op == "get") + return(prefs.getCharPref(prefName)); + else + return(prefs.setCharPref(prefName, prefValue)); + case "COMPLEX": + if (aMessage.json.op == "get") + return(prefs.getComplexValue(prefName, prefValue[0])); + else + return(prefs.setComplexValue(prefName, prefValue[0], prefValue[1])); + case "": + if (aMessage.json.op == "clear") { + prefs.clearUserPref(prefName); + return; + } + } + break; + + case "SPProcessCrashService": + switch (aMessage.json.op) { + case "register-observer": + this.addProcessCrashObservers(); + break; + case "unregister-observer": + this.removeProcessCrashObservers(); + break; + case "delete-crash-dump-files": + return this.deleteCrashDumpFiles(aMessage.json.filenames); + case "find-crash-dump-files": + return this.findCrashDumpFiles(aMessage.json.crashDumpFilesToIgnore); + default: + throw new SpecialPowersException("Invalid operation for SPProcessCrashService"); + } + break; + + case "SPPingService": + if (aMessage.json.op == "ping") { + aMessage.target + .QueryInterface(Ci.nsIFrameLoaderOwner) + .frameLoader + .messageManager + .sendAsyncMessage("SPPingService", { op: "pong" }); + } + break; + + default: + throw new SpecialPowersException("Unrecognized Special Powers API"); + } + } +}; + +const NSGetFactory = XPCOMUtils.generateNSGetFactory([SpecialPowersObserver]); diff --git a/test/resources/firefox/extensions/special-powers@mozilla.org/install.rdf b/test/resources/firefox/extensions/special-powers@mozilla.org/install.rdf new file mode 100644 index 000000000..490d4ddaf --- /dev/null +++ b/test/resources/firefox/extensions/special-powers@mozilla.org/install.rdf @@ -0,0 +1,26 @@ + + + + + + special-powers@mozilla.org + 2010.07.23 + 2 + + + + + toolkit@mozilla.org + 3.0 + 13.0a1 + + + + + Special Powers + Special powers for use in testing. + Mozilla + + diff --git a/test/resources/firefox/prefs.js b/test/resources/firefox/prefs.js new file mode 100644 index 000000000..8d59d66bd --- /dev/null +++ b/test/resources/firefox/prefs.js @@ -0,0 +1 @@ +user_pref("browser.shell.checkDefaultBrowser", false); diff --git a/test/resources/firefox/user.js b/test/resources/firefox/user.js new file mode 100644 index 000000000..b7f9845f7 --- /dev/null +++ b/test/resources/firefox/user.js @@ -0,0 +1,40 @@ +'use strict'; + +user_pref('browser.console.showInPanel', true); +user_pref('browser.dom.window.dump.enabled', true); +user_pref('browser.firstrun.show.localepicker', false); +user_pref('browser.firstrun.show.uidiscovery', false); +user_pref('dom.allow_scripts_to_close_windows', true); +user_pref('dom.disable_open_during_load', false); +user_pref('dom.max_script_run_time', 0); // no slow script dialogs +user_pref('dom.max_chrome_script_run_time', 0); +user_pref('dom.popup_maximum', -1); +user_pref('dom.send_after_paint_to_content', true); +user_pref('dom.successive_dialog_time_limit', 0); +user_pref('security.warn_submit_insecure', false); +user_pref('browser.shell.checkDefaultBrowser', false); +user_pref('shell.checkDefaultClient', false); +user_pref('browser.warnOnQuit', false); +user_pref('accessibility.typeaheadfind.autostart', false); +user_pref('javascript.options.showInConsole', true); +user_pref('devtools.errorconsole.enabled', true); +user_pref('layout.debug.enable_data_xbl', true); +user_pref('browser.EULA.override', true); +user_pref('javascript.options.tracejit.content', true); +user_pref('javascript.options.methodjit.content', true); +user_pref('javascript.options.jitprofiling.content', true); +user_pref('javascript.options.methodjit_always', false); +user_pref('gfx.color_management.force_srgb', true); +user_pref('network.manage-offline-status', false); +user_pref('test.mousescroll', true); +user_pref('network.http.prompt-temp-redirect', false); +user_pref('media.cache_size', 100); +user_pref('security.warn_viewing_mixed', false); +user_pref('app.update.enabled', false); +user_pref('browser.panorama.experienced_first_run', true); // Assume experienced +user_pref('dom.w3c_touch_events.enabled', true); +user_pref('extensions.checkCompatibility', false); +user_pref('extensions.installDistroAddons', false); // prevent testpilot etc +user_pref('browser.safebrowsing.enable', false); // prevent traffic to google servers +user_pref('toolkit.telemetry.prompted', true); // prevent telemetry banner +user_pref('toolkit.telemetry.enabled', false); diff --git a/test/resources/reftest-analyzer.xhtml b/test/resources/reftest-analyzer.xhtml new file mode 100644 index 000000000..e4071f232 --- /dev/null +++ b/test/resources/reftest-analyzer.xhtml @@ -0,0 +1,601 @@ + + + + + + + Reftest analyzer + + + + + + +
+ +

Reftest analyzer: load reftest log

+ +

Either paste your log into this textarea:
+