Merge branch 'master' into ir-2

This commit is contained in:
Michael Bebenita 2012-12-06 18:13:39 -08:00
Родитель 5fd2818246 181095ec0b
Коммит 720673fe5b
163 изменённых файлов: 7564 добавлений и 2965 удалений

3
.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

3
.gitmodules поставляемый
Просмотреть файл

@ -4,3 +4,6 @@
[submodule "lib/DataView.js"]
path = lib/DataView.js
url = https://github.com/davidflanagan/DataView.js.git
[submodule "lib/xstats"]
path = lib/xstats
url = https://github.com/bestiejs/xstats.js.git

Просмотреть файл

@ -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..."
@ -32,10 +33,33 @@ build-playerglobal:
build-extension:
make -C extension/firefox/ build
build-web:
make -C web/ build
update-flash-refs:
node utils/update-flash-refs.js extension/firefox/content/web/viewer.html src/flash
node utils/update-flash-refs.js examples/inspector/inspector.html src/flash
node utils/update-flash-refs.js examples/racing/index.html src/flash
node utils/update-flash-refs.js test/harness/slave.html src/flash
test:
make -C src/avm1/tests/ test
make -C src/avm2/bin/ test-regress
BROWSER_MANIFEST ?= resources/browser_manifests/browser_manifest.json
check-browser-manifest:
@ls test/$(BROWSER_MANIFEST) || { echo "ERROR: Browser manifest file is not found at test/$(BROWSER_MANIFEST). Create one using the examples at test/resources/browser_manifests/."; exit 1; }
reftest: check-browser-manifest
cd test; python test.py --reftest --browserManifestFile=$(BROWSER_MANIFEST)
makeref: check-browser-manifest
cd test; python test.py --masterMode --browserManifestFile=$(BROWSER_MANIFEST)
reftest-swfdec: check-browser-manifest
cd test; python test.py --reftest --browserManifestFile=$(BROWSER_MANIFEST) --manifestFile=swfdec_test_manifest.json
hello-world:
make -C src/avm2/bin/ hello-world
@ -86,4 +110,7 @@ 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 \
reftest reftest-swfdec makeref check-browser-manifest

Просмотреть файл

@ -1,71 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>AS3 Tiger</title>
</head>
<body>
<div id="stage"></div>
<script src="../../src/swf/util.js"></script>
<script src="../../src/swf/swf.js"></script>
<script>
SWF.workerPath = "../../src/swf/worker.js";
</script>
<script src="../../src/swf/worker.js"></script>
<script src="../../src/swf/prototypes.js"></script>
<script src="../../src/swf/embed.js"></script>
<script src="../../src/swf/renderer.js"></script>
<script>
window.print = function (msg) {
console.log(msg);
};
var webShell = true;
</script>
<script src="../../src/avm2/DataView.js"></script>
<script src="../../src/avm2/util.js"></script>
<script>
var options = new OptionSet("option(s)");
var disassemble = options.register(new Option("disassemble", "d", false, "disassemble"));
var traceLevel = options.register(new Option("traceLevel", "t", 0, "trace level"));
</script>
<script src="../../src/avm2/constants.js"></script>
<script src="../../src/avm2/opcodes.js"></script>
<script src="../../src/avm2/parser.js"></script>
<script src="../../src/avm2/disassembler.js"></script>
<script src="../../src/avm2/analyze.js"></script>
<script src="../../src/avm2/compiler.js"></script>
<script src="../../src/avm2/native.js"></script>
<script src="../../src/avm2/runtime.js"></script>
<script src="../../src/avm2/interpreter.js"></script>
<script src="../../src/flash/events/EventDispatcher.js"></script>
<script src="../../src/flash/display/DisplayObject.js"></script>
<script src="../../src/flash/display/InteractiveObject.js"></script>
<script src="../../src/flash/display/DisplayObjectContainer.js"></script>
<script src="../../src/flash/display/Graphics.js"></script>
<script src="../../src/flash/display/Sprite.js"></script>
<script src="../../src/flash/display/MovieClip.js"></script>
<script>
var abcFiles = [];
var filesLoaded = 0;
["builtin", "playerGlobal"].forEach(function (v, i, a) {
var xhr = new XMLHttpRequest;
xhr.open("GET", "../../src/avm2/generated/" + v + "/" + v + ".abc");
xhr.responseType = "arraybuffer";
xhr.onload = function () {
abcFiles[i] = new AbcFile(new Uint8Array(this.response), v, true);
if (++filesLoaded === a.length) {
abcFiles.forEach(function (abc) {
(filesLoaded === 1 ? executeAbc : loadAbc)(abc, EXECUTION_MODE.INTERPRET);
});
SWF.embed("../../examples/as3_tiger/tiger.swf", document.getElementById("stage"));
}
}
xhr.send();
});
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,24 @@
package {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.geom.Rectangle;
public class BitmapTests extends Sprite {
//---------------------- Public Properties ----------------------//
//---------------------- Private / Protected Properties ----------------------//
//---------------------- Public Methods ----------------------//
public function BitmapTests() {
var bits : BitmapData = new BitmapData(100, 100, false, 0xff0000);
var bitmap : Bitmap = new Bitmap(bits);
addChild(bitmap);
bits.fillRect(new Rectangle(10, 10, 80, 80), 0x0000ff);
}
//---------------------- Private / Protected Methods ----------------------//
}
}

Двоичные данные
examples/bitmap/bitmap.swf Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -6,11 +6,14 @@
<link rel="stylesheet" href="style/style.css">
</head>
<body>
<div id="stage"></div>
<div id="stage">
<div id="xstats"></div>
</div>
<script src="jquery.min.js"></script>
<script src="../../lib/DataView.js/DataView.js"></script>
<script src="../../lib/Kanvas/kanvas.js"></script>
<script src="../../lib/xstats/xstats.js"></script>
<!-- Load SWF Dependencies -->
<script src="../../src/swf/util.js"></script>
@ -96,46 +99,53 @@
<!-- Load Flash Dependencies -->
<script src="../../src/flash/util.js"></script>
<script src="../../src/flash/events/Event.js"></script>
<script src="../../src/flash/events/KeyboardEvent.js"></script>
<script src="../../src/flash/events/TimerEvent.js"></script>
<script src="../../src/flash/events/EventDispatcher.js"></script>
<script src="../../src/flash/net/NetConnection.js"></script>
<script src="../../src/flash/net/NetStream.js"></script>
<!-- Autogenerated flash references: base=../../src/flash/ -->
<script src="../../src/flash/display/Bitmap.js"></script>
<script src="../../src/flash/display/BitmapData.js"></script>
<script src="../../src/flash/display/DisplayObject.js"></script>
<script src="../../src/flash/display/InteractiveObject.js"></script>
<script src="../../src/flash/display/DisplayObjectContainer.js"></script>
<script src="../../src/flash/display/Sprite.js"></script>
<script src="../../src/flash/display/MovieClip.js"></script>
<script src="../../src/flash/display/Graphics.js"></script>
<script src="../../src/flash/display/InteractiveObject.js"></script>
<script src="../../src/flash/display/Loader.js"></script>
<script src="../../src/flash/display/LoaderInfo.js"></script>
<script src="../../src/flash/display/Stage.js"></script>
<script src="../../src/flash/display/BitmapData.js"></script>
<script src="../../src/flash/display/Graphics.js"></script>
<script src="../../src/flash/display/MorphShape.js"></script>
<script src="../../src/flash/display/MovieClip.js"></script>
<script src="../../src/flash/display/Shape.js"></script>
<script src="../../src/flash/display/SimpleButton.js"></script>
<script src="../../src/flash/display/Sprite.js"></script>
<script src="../../src/flash/display/Stage.js"></script>
<script src="../../src/flash/events/Event.js"></script>
<script src="../../src/flash/events/EventDispatcher.js"></script>
<script src="../../src/flash/events/KeyboardEvent.js"></script>
<script src="../../src/flash/events/MouseEvent.js"></script>
<script src="../../src/flash/events/TextEvent.js"></script>
<script src="../../src/flash/events/TimerEvent.js"></script>
<script src="../../src/flash/external/ExternalInterface.js"></script>
<script src="../../src/flash/geom/ColorTransform.js"></script>
<script src="../../src/flash/geom/Matrix.js"></script>
<script src="../../src/flash/geom/Point.js"></script>
<script src="../../src/flash/geom/Rectangle.js"></script>
<script src="../../src/flash/geom/Matrix.js"></script>
<script src="../../src/flash/geom/ColorTransform.js"></script>
<script src="../../src/flash/geom/Transform.js"></script>
<!--
<script src="../../src/flash/media/Sound.js"></script>
<script src="../../src/flash/media/SoundMixer.js"></script>
<script src="../../src/flash/media/SoundTransform.js"></script>
-->
<script src="../../src/flash/media/Video.js"></script>
<!--
<script src="../../src/flash/net/NetConnection.js"></script>
<script src="../../src/flash/net/NetStream.js"></script>
<script src="../../src/flash/net/Responder.js"></script>
<script src="../../src/flash/net/URLRequest.js"></script>
<script src="../../src/flash/system/Capabilities.js"></script>
<script src="../../src/flash/system/FSCommand.js"></script>
<script src="../../src/flash/text/Font.js"></script>
-->
<script src="../../src/flash/text/StaticText.js"></script>
<script src="../../src/flash/text/TextField.js"></script>
<script src="../../src/flash/ui/Keyboard.js"></script>
<!--
<script src="../../src/flash/ui/Mouse.js"></script>
-->
<script src="../../src/flash/utils/Timer.js"></script>
<!-- Autogenerated flash references end -->
<script src="../../src/flash/stubs.js"></script>
<input type="file" id="files" name="files[]" multiple style="visibility: hidden;">
<input type="file" id="files" name="files[]" multiple style="visibility: hidden;" accept="application/x-shockwave-flash">
<!--
Shameless copying from:
@ -143,9 +153,13 @@
-->
<div class="toolbarGroup">
<div class="toolbarBox withEmphasis" style="position: fixed; bottom: 380px; left: auto; right: 0px; width: 300px;" hidden>
<div class="closeButton"></div>
<div class="toolbarLabel " style="width: 240px; text-align: left;" id="message">Test</div>
</div>
<div class="toolbarInfo" style="position: fixed; bottom: 70px; left: auto; right: 0px; width: 300px; height: 300px;" id="info">
</div>
<div class="toolbarBox" style="position: fixed; bottom: 35px; left: 0; right: 0; width: auto;">
<div class="toolbarBox" style="position: fixed; bottom: 35px; left: 0; right: 0; width: auto;" id="openFileToolbar">
<div class="closeButton"></div>
<div class="toolbarLabel " style="width: 140px; text-align: left;">Shumway Inspector</div>
<div class="toolbarButton" id="openFile" title="Select SWF/ABC file (or drag'n'drop the file on the stage).">Open File</div>
@ -166,7 +180,12 @@
<script src="inspector.js"></script>
<script>
SHUMWAY_ROOT = "../../";
SHUMWAY_ROOT = "../../src/";
</script>
<script>
var stats = new xStats;
document.getElementById('xstats').appendChild(stats.element);
</script>
</body>

Просмотреть файл

@ -65,13 +65,19 @@ var playerGlobalPath = "../../src/flash/playerGlobal.min.abc";
* when the page loads.
*/
if (rfile) {
$('#openFileToolbar')[0].setAttribute('hidden', true);
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")) {

Просмотреть файл

@ -34,3 +34,6 @@ $("#openFile").click(function () {
$("#files").click();
});
$(".closeButton").click(function (event) {
event.target.parentElement.setAttribute('hidden', true);
});

Просмотреть файл

@ -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) {

Просмотреть файл

@ -12,7 +12,7 @@ body {
@media screen and (-webkit-min-device-pixel-ratio:0) {
body {
background: #1a2633;
background-color: #1a2633;
}
}
@ -22,15 +22,23 @@ body {
}
.toolbarInfo {
font-family: Consolas, Lucida Grande, sans-serif;
padding: 4px 8px;
background: url(images/background-noise-toolbar.png),
background-image: url(images/background-noise-toolbar.png),
linear-gradient(hsl(210,11%,36%), hsl(210,11%,18%));
background-image: url(images/background-noise-toolbar.png),
-moz-linear-gradient(hsl(210,11%,36%), hsl(210,11%,18%));
background-image: url(images/background-noise-toolbar.png),
-webkit-linear-gradient(hsl(210,11%,36%), hsl(210,11%,18%));
background-image: url(images/background-noise-toolbar.png),
-o-linear-gradient(hsl(210,11%,36%), hsl(210,11%,18%));
background-image: url(images/background-noise-toolbar.png),
-ms-linear-gradient(hsl(210,11%,36%), hsl(210,11%,18%));
border-radius: 4px;
box-shadow: 0 1px 0 hsla(210,16%,76%,.2) inset,
0 0 0 1px hsla(0,0%,0%,.15),
0 10px 14px hsla(0,0%,0%,.4);
font-family: Consolas, Lucida Grande, sans-serif;
0 10px 14px hsla(0,0%,0%,.4),
0 0 0 1px hsla(210,16%,76%,.15) inset,
0 1px 0 hsla(210,16%,76%,.15);
color: hsl(210,30%,85%);
@ -38,10 +46,8 @@ body {
line-height: 22px;
text-shadow: 0 -1px 0 hsla(210,8%,5%,.45);
cursor: default;
line-height: 1.2em;
font-size: 11px;
overflow-x: auto;
}
@ -49,8 +55,17 @@ body {
padding: 4px 8px;
width: 600px;
height: 24px;
background: url(images/background-noise-toolbar.png),
linear-gradient(hsl(210,11%,36%), hsl(210,11%,18%));
background: url(images/background-noise-toolbar.png),
-moz-linear-gradient(hsl(210,11%,36%), hsl(210,11%,18%));
background: url(images/background-noise-toolbar.png),
-webkit-linear-gradient(hsl(210,11%,36%), hsl(210,11%,18%));
background: url(images/background-noise-toolbar.png),
-o-linear-gradient(hsl(210,11%,36%), hsl(210,11%,18%));
background: url(images/background-noise-toolbar.png),
-ms-linear-gradient(hsl(210,11%,36%), hsl(210,11%,18%));
background: url(images/background-noise-toolbar.png),
border-radius: 4px;
box-shadow: 0 1px 0 hsla(210,16%,76%,.2) inset,
0 0 0 1px hsla(0,0%,0%,.15),
@ -58,6 +73,24 @@ body {
font-family: Lucida Grande, sans-serif;
}
.toolbarBox.withEmphasis {
background: url(images/background-noise-toolbar.png),
linear-gradient(hsl(0,51%,36%), hsl(0,51%,18%));
background: url(images/background-noise-toolbar.png),
-moz-linear-gradient(hsl(0,51%,36%), hsl(0,51%,18%));
background: url(images/background-noise-toolbar.png),
-webkit-linear-gradient(hsl(0,51%,36%), hsl(0,51%,18%));
background: url(images/background-noise-toolbar.png),
-o-linear-gradient(hsl(0,51%,36%), hsl(0,51%,18%));
background: url(images/background-noise-toolbar.png),
-ms-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;
@ -79,14 +112,16 @@ body {
width: 78px;
height: 22px;
margin-right: 10px;
0 0 0 1px hsla(210,16%,76%,.15) inset,
0 1px 0 hsla(210,16%,76%,.15);
color: hsl(210,30%,85%);
font-size: 12px;
line-height: 22px;
text-align: center;
text-shadow: 0 -1px 0 hsla(210,8%,5%,.45);
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
-o-user-select: none;
-ms-user-select: none;
cursor: default;
}
@ -97,7 +132,11 @@ body {
margin-right: 10px;
border: 1px solid hsla(210,8%,5%,.45);
border-radius: 3px;
background: linear-gradient(hsla(212,7%,57%,.35), hsla(212,7%,57%,.1));
background: -moz-linear-gradient(hsla(212,7%,57%,.35), hsla(212,7%,57%,.1));
background: -webkit-linear-gradient(hsla(212,7%,57%,.35), hsla(212,7%,57%,.1));
background: -o-linear-gradient(hsla(212,7%,57%,.35), hsla(212,7%,57%,.1));
background: -ms-linear-gradient(hsla(212,7%,57%,.35), hsla(212,7%,57%,.1));
background-clip: padding-box;
box-shadow: 0 1px 0 hsla(210,16%,76%,.15) inset,
0 0 0 1px hsla(210,16%,76%,.15) inset,
@ -107,13 +146,21 @@ body {
line-height: 22px;
text-align: center;
text-shadow: 0 -1px 0 hsla(210,8%,5%,.45);
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
-o-user-select: none;
-ms-user-select: none;
cursor: default;
}
.toolbarButton:not(.pressedState):hover:active {
border: 1px solid hsla(210,8%,5%,.6);
background: linear-gradient(hsla(220,6%,10%,.3), hsla(212,7%,57%,.15) 65%, hsla(212,7%,57%,.3));
background: -moz-linear-gradient(hsla(220,6%,10%,.3), hsla(212,7%,57%,.15) 65%, hsla(212,7%,57%,.3));
background: -webkit-linear-gradient(hsla(220,6%,10%,.3), hsla(212,7%,57%,.15) 65%, hsla(212,7%,57%,.3));
background: -o-linear-gradient(hsla(220,6%,10%,.3), hsla(212,7%,57%,.15) 65%, hsla(212,7%,57%,.3));
background: -ms-linear-gradient(hsla(220,6%,10%,.3), hsla(212,7%,57%,.15) 65%, hsla(212,7%,57%,.3));
box-shadow: 0 0 3px hsla(210,8%,5%,.25) inset,
0 1px 3px hsla(210,8%,5%,.25) inset,
0 1px 0 hsla(210,16%,76%,.15);
@ -121,7 +168,11 @@ body {
.toolbarButton.pressedState {
border: 1px solid hsla(210,8%,5%,.6);
background: linear-gradient(hsla(220,6%,10%,.6), hsla(210,11%,18%,.45) 75%, hsla(210,11%,30%,.4));
background: -moz-linear-gradient(hsla(220,6%,10%,.6), hsla(210,11%,18%,.45) 75%, hsla(210,11%,30%,.4));
background: -webkit-linear-gradient(hsla(220,6%,10%,.6), hsla(210,11%,18%,.45) 75%, hsla(210,11%,30%,.4));
background: -o-linear-gradient(hsla(220,6%,10%,.6), hsla(210,11%,18%,.45) 75%, hsla(210,11%,30%,.4));
background: -ms-linear-gradient(hsla(220,6%,10%,.6), hsla(210,11%,18%,.45) 75%, hsla(210,11%,30%,.4));
box-shadow: 0 1px 3px hsla(210,8%,5%,.25) inset,
0 1px 3px hsla(210,8%,5%,.25) inset,
0 1px 0 hsla(210,16%,76%,.15);
@ -142,7 +193,11 @@ body {
line-height: 22px;
text-align: center;
text-shadow: 0 -1px 0 hsla(210,8%,5%,.45);
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
-o-user-select: none;
-ms-user-select: none;
cursor: default;
}
@ -151,10 +206,18 @@ body {
padding: 0 4px;
height: 24px;
border-width: 0 13px 0 8px;
border-image: url(images/breadcrumb-mac-start.png) 0 13 0 8 repeat;
-moz-border-image: url(images/breadcrumb-mac-start.png) 0 13 0 8 repeat;
-webkit-border-image: url(images/breadcrumb-mac-start.png) 0 13 0 8 repeat;
-o-border-image: url(images/breadcrumb-mac-start.png) 0 13 0 8 repeat;
-ms-border-image: url(images/breadcrumb-mac-start.png) 0 13 0 8 repeat;
}
.breadcrumbBarStart:hover:active {
border-image: url(images/breadcrumb-mac-start-pressed.png) 0 13 0 8 repeat;
-moz-border-image: url(images/breadcrumb-mac-start-pressed.png) 0 13 0 8 repeat;
-webkit-border-image: url(images/breadcrumb-mac-start-pressed.png) 0 13 0 8 repeat;
-o-border-image: url(images/breadcrumb-mac-start-pressed.png) 0 13 0 8 repeat;
-ms-border-image: url(images/breadcrumb-mac-start-pressed.png) 0 13 0 8 repeat;
}
.breadcrumbBarMiddle {
@ -163,10 +226,18 @@ body {
float: left;
height: 24px;
border-width: 0 13px;
border-image: url(images/breadcrumb-mac-middle.png) 0 13 0 13 repeat;
-moz-border-image: url(images/breadcrumb-mac-middle.png) 0 13 0 13 repeat;
-webkit-border-image: url(images/breadcrumb-mac-middle.png) 0 13 0 13 repeat;
-o-border-image: url(images/breadcrumb-mac-middle.png) 0 13 0 13 repeat;
-moz-border-image: url(images/breadcrumb-mac-middle.png) 0 13 0 13 repeat;
}
.breadcrumbBarMiddle:hover:active {
border-image: url(images/breadcrumb-mac-middle-pressed.png) 0 13 0 13 repeat;
-moz-border-image: url(images/breadcrumb-mac-middle-pressed.png) 0 13 0 13 repeat;
-webkit-border-image: url(images/breadcrumb-mac-middle-pressed.png) 0 13 0 13 repeat;
-o-border-image: url(images/breadcrumb-mac-middle-pressed.png) 0 13 0 13 repeat;
-ms-border-image: url(images/breadcrumb-mac-middle-pressed.png) 0 13 0 13 repeat;
}
.breadcrumbBarEnd {
@ -175,37 +246,70 @@ body {
float: left;
height: 24px;
border-width: 0 8px 0 13px;
border-image: url(images/breadcrumb-mac-end-selected.png) 0 8 0 13 repeat;
-moz-border-image: url(images/breadcrumb-mac-end-selected.png) 0 8 0 13 repeat;
-webkit-border-image: url(images/breadcrumb-mac-end-selected.png) 0 8 0 13 repeat;
-o-border-image: url(images/breadcrumb-mac-end-selected.png) 0 8 0 13 repeat;
-ms-border-image: url(images/breadcrumb-mac-end-selected.png) 0 8 0 13 repeat;
color: hsl(208,100%,60%);
}
.breadcrumbBarEnd:hover:active {
border-image: url(images/breadcrumb-mac-end-selected-pressed.png) 0 8 0 13 repeat;
-moz-border-image: url(images/breadcrumb-mac-end-selected-pressed.png) 0 8 0 13 repeat;
-webkit-border-image: url(images/breadcrumb-mac-end-selected-pressed.png) 0 8 0 13 repeat;
-o-border-image: url(images/breadcrumb-mac-end-selected-pressed.png) 0 8 0 13 repeat;
-ms-border-image: url(images/breadcrumb-mac-end-selected-pressed.png) 0 8 0 13 repeat;
}
.textInput {
float: left;
appearance: none;
-moz-appearance: none;
-webkit-appearance: none;
-o-appearance: none;
-ms-appearance: none;
margin: 0 3px;
background-color: transparent;
height: 22px;
border: 1px solid hsla(210,8%,5%,.6);
border-radius: 6px;
background-image: linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
background-image: -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
background-image: -webkit-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
background-image: -o-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
background-image: -ms-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
background-repeat: no-repeat;
background-position: 4px center, top left, top left;
padding-top: 0;
padding-bottom: 0;
padding-start: 10px;
-moz-padding-start: 10px;
-webkit-padding-start: 10px;
-o-padding-start: 10px;
-ms-padding-start: 10px;
padding-end: 4px;
-moz-padding-end: 4px;
-webkit-padding-end: 4px;
-o-padding-end: 4px;
-ms-padding-end: 4px;
box-shadow: 0 1px 1px hsla(210,8%,5%,.3) inset,
0 0 0 1px hsla(210,16%,76%,.1) inset,
0 1px 0 hsla(210,16%,76%,.15);
color: hsl(210,30%,85%);
font-weight: bolder;
}
.textInput:-moz-locale-dir(rtl) {
background-position: calc(100% - 4px) center, top left, top left;
}
#stage {
float: left;
}
#xstats {
position: absolute;
right: 0;
top: 0;
z-index: 1;
}

Двоичные данные
examples/pac/pac.fla

Двоичный файл не отображается.

Двоичные данные
examples/pac/pac.swf

Двоичный файл не отображается.

Просмотреть файл

@ -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);
}
});
}

Просмотреть файл

@ -24,9 +24,10 @@
color: Yellow;
}
</style>
</head>
<body>
<div id="stage"></div>
<script>
SHUMWAY_ROOT = "../../src/";
</script>
<script src="../../lib/DataView.js/DataView.js"></script>
<script src="../../lib/Kanvas/kanvas.js"></script>
@ -50,9 +51,6 @@
<script src="../../src/swf/shape.js"></script>
<script src="../../src/swf/text.js"></script>
<script src="../../src/swf/prototypes.js"></script>
<!-- Load AVM1 Dependencies -->
<script src="../../src/avm1/classes.js"></script>
<script src="../../src/avm1/globals.js"></script>
@ -61,29 +59,108 @@
<script src="../../src/swf/embed.js"></script>
<script src="../../src/swf/renderer.js"></script>
<script src="../../src/flash/util.js"></script>
<script src="../../src/flash/events/Event.js"></script>
<script src="../../src/flash/events/ProgressEvent.js"></script>
<script src="../../src/flash/events/EventDispatcher.js"></script>
<script src="../../src/flash/display/DisplayObject.js"></script>
<script src="../../src/flash/display/InteractiveObject.js"></script>
<script src="../../src/flash/display/DisplayObjectContainer.js"></script>
<script src="../../src/flash/display/Graphics.js"></script>
<script src="../../src/flash/display/Sprite.js"></script>
<script src="../../src/flash/display/Loader.js"></script>
<script src="../../src/flash/display/LoaderInfo.js"></script>
<script src="../../src/flash/display/MovieClip.js"></script>
<script src="../../src/flash/display/Stage.js"></script>
<script src="../../src/flash/display/StaticText.js"></script>
<script src="../../src/flash/ui/Keyboard.js"></script>
<script src="../../src/flash/ui/Mouse.js"></script>
<!-- Load AVM2 Dependencies -->
<script src="../../src/avm2/util.js"></script>
<script src="../../src/avm2/options.js"></script>
<script src="../../src/avm2/metrics.js"></script>
<script>
Loader.LOADER_PATH = "../../src/flash/display/Loader.js";
var Counter = new metrics.Counter(true);
var Timer = metrics.Timer;
var Option = options.Option;
var OptionSet = options.OptionSet;
var systemOptions = new OptionSet("System Options");
var disassemble = systemOptions.register(new Option("d", "disassemble", "boolean", false, "disassemble"));
var traceLevel = systemOptions.register(new Option("t", "traceLevel", "number", 0, "trace level"));
window.print = function(s) {
console.log(s);
};
</script>
<script src="../../src/avm2/constants.js"></script>
<script src="../../src/avm2/errors.js"></script>
<script src="../../src/avm2/opcodes.js"></script>
<script src="../../src/avm2/parser.js"></script>
<script src="../../src/avm2/analyze.js"></script>
<script src="../../src/avm2/compiler/lljs/src/estransform.js"></script>
<script src="../../src/avm2/compiler/lljs/src/escodegen.js"></script>
<script src="../../src/avm2/compiler/inferrer.js"></script>
<script src="../../src/avm2/compiler/compiler.js"></script>
<script src="../../src/avm2/domain.js"></script>
<script src="../../src/avm2/runtime.js"></script>
<script src="../../src/avm2/native.js"></script>
<script src="../../src/avm2/disassembler.js"></script>
<script src="../../src/avm2/interpreter.js"></script>
<script src="../../src/avm2/vm.js"></script>
<script src="avm2utils.js"></script>
<!-- Load Flash Dependencies -->
<script src="../../src/flash/util.js"></script>
<!-- Autogenerated flash references: base=../../src/flash/ -->
<script src="../../src/flash/display/Bitmap.js"></script>
<script src="../../src/flash/display/BitmapData.js"></script>
<script src="../../src/flash/display/DisplayObject.js"></script>
<script src="../../src/flash/display/DisplayObjectContainer.js"></script>
<script src="../../src/flash/display/Graphics.js"></script>
<script src="../../src/flash/display/InteractiveObject.js"></script>
<script src="../../src/flash/display/Loader.js"></script>
<script src="../../src/flash/display/LoaderInfo.js"></script>
<script src="../../src/flash/display/MorphShape.js"></script>
<script src="../../src/flash/display/MovieClip.js"></script>
<script src="../../src/flash/display/Shape.js"></script>
<script src="../../src/flash/display/SimpleButton.js"></script>
<script src="../../src/flash/display/Sprite.js"></script>
<script src="../../src/flash/display/Stage.js"></script>
<script src="../../src/flash/events/Event.js"></script>
<script src="../../src/flash/events/EventDispatcher.js"></script>
<script src="../../src/flash/events/KeyboardEvent.js"></script>
<script src="../../src/flash/events/MouseEvent.js"></script>
<script src="../../src/flash/events/TextEvent.js"></script>
<script src="../../src/flash/events/TimerEvent.js"></script>
<script src="../../src/flash/external/ExternalInterface.js"></script>
<script src="../../src/flash/geom/ColorTransform.js"></script>
<script src="../../src/flash/geom/Matrix.js"></script>
<script src="../../src/flash/geom/Point.js"></script>
<script src="../../src/flash/geom/Rectangle.js"></script>
<script src="../../src/flash/geom/Transform.js"></script>
<script src="../../src/flash/media/Sound.js"></script>
<script src="../../src/flash/media/SoundMixer.js"></script>
<script src="../../src/flash/media/SoundTransform.js"></script>
<script src="../../src/flash/media/Video.js"></script>
<script src="../../src/flash/net/NetConnection.js"></script>
<script src="../../src/flash/net/NetStream.js"></script>
<script src="../../src/flash/net/Responder.js"></script>
<script src="../../src/flash/net/URLRequest.js"></script>
<script src="../../src/flash/system/Capabilities.js"></script>
<script src="../../src/flash/system/FSCommand.js"></script>
<script src="../../src/flash/text/Font.js"></script>
<script src="../../src/flash/text/StaticText.js"></script>
<script src="../../src/flash/text/TextField.js"></script>
<script src="../../src/flash/ui/Keyboard.js"></script>
<script src="../../src/flash/ui/Mouse.js"></script>
<script src="../../src/flash/utils/Timer.js"></script>
<!-- Autogenerated flash references end -->
<script src="../../src/flash/stubs.js"></script>
</head>
<body>
<div id="stage"></div>
<script>
SWF.embed("../../examples/racing/race.swf", document.getElementById("stage"));
var SWF_PATH = "race.swf";
createAVM2(builtinPath, playerGlobalPath, EXECUTION_MODE.INTERPRET, EXECUTION_MODE.COMPILE, function (avm2) {
function loaded() {}
new BinaryFileReader(SWF_PATH).readAll(null, function(buffer) {
if (!buffer) {
throw "Unable to open the file " + SWF_PATH + ": " + error;
}
SWF.embed(buffer, document.getElementById("stage"), { onComplete: loaded });
});
});
</script>
<div id="footer">
<sup>*</sup>

1
extension/firefox/.gitignore поставляемый
Просмотреть файл

@ -1,3 +1,4 @@
build/*
content/swf/*
content/flash/*
content/avm1/*

Просмотреть файл

@ -1,6 +1,63 @@
# Just builds a ff extension
build:
VERSION_BASELINE=c9d3aa7c886ce53648082
VERSION=0.3.`git log --format=oneline $(VERSION_BASELINE)..|wc -l|tr -d ' '`
build: clean
# Coping extension files
echo "Creating extension verions: $(VERSION)"
mkdir 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/
mkdir build/content/flash
cp ../../src/flash/*.js build/content/flash/
cp ../../src/flash/playerGlobal.min.abc build/content/flash/
mkdir build/content/flash/display
cp ../../src/flash/display/*.js build/content/flash/display/
mkdir build/content/flash/events
cp ../../src/flash/events/*.js build/content/flash/events/
mkdir build/content/flash/geom
cp ../../src/flash/geom/*.js build/content/flash/geom/
mkdir build/content/flash/media
cp ../../src/flash/media/*.js build/content/flash/media/
mkdir build/content/flash/net
cp ../../src/flash/net/*.js build/content/flash/net/
mkdir build/content/flash/system
cp ../../src/flash/system/*.js build/content/flash/system/
mkdir build/content/flash/text
cp ../../src/flash/text/*.js build/content/flash/text/
mkdir build/content/flash/ui
cp ../../src/flash/ui/*.js build/content/flash/ui/
mkdir build/content/flash/utils
cp ../../src/flash/utils/*.js build/content/flash/utils/
mkdir build/content/avm1
cp ../../src/avm1/*.js build/content/avm1/
mkdir build/content/avm2
cp ../../src/avm2/*.js build/content/avm2/
mkdir build/content/avm2/compiler
cp ../../src/avm2/compiler/*.js build/content/avm2/compiler/
mkdir -p build/content/avm2/compiler/lljs/src
cp ../../src/avm2/compiler/lljs/src/*.js build/content/avm2/compiler/lljs/src/
mkdir -p build/content/avm2/generated/builtin
cp ../../src/avm2/generated/builtin/builtin.abc build/content/avm2/generated/builtin/
mkdir build/content/lib
mkdir build/content/lib/Kanvas
cp ../../lib/Kanvas/* build/content/lib/Kanvas/
mkdir build/content/lib/DataView.js
cp ../../lib/DataView.js/* build/content/lib/DataView.js/
# Removing hidden files
-find build -name ".DS_Store" -exec rm {} \;
# Packaging XPI file
cd build; zip -r shumway.xpi *
clean: legacy-clean
-rm -rf build
legacy-clean:
# Cleaning old files
-rm -rf content/swf
-rm -rf content/flash
@ -8,40 +65,7 @@ build:
-rm -rf content/avm2
-rm -rf content/glue
-rm -rf content/lib
-rm LICENSE
-rm shumway.xpi
# Coping JavaScript content files
mkdir content/swf
cp ../../src/swf/*.js content/swf/
mkdir content/flash
cp ../../src/flash/*.js 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/ui
cp ../../src/flash/ui/*.js content/flash/ui/
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
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/
mkdir content/lib/DataView.js
cp ../../lib/DataView.js/* content/lib/DataView.js/
cp ../../LICENSE .
# Removing hidden files
-find . -name ".DS_Store" | xargs rm
# Packaging XPI file
zip -r shumway.xpi install.rdf bootstrap.js content components LICENSE
PHONY: build clean legacy-clean

Просмотреть файл

@ -0,0 +1,62 @@
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);
}
});
}

Просмотреть файл

@ -5,7 +5,11 @@
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>Shumway viewer</title>
<script>
SHUMWAY_ROOT = "resource://shumway/";
</script>
<!-- <base href="resource://shumway/web/viewer.html" /> -->
<script src="../lib/DataView.js/DataView.js"></script>
<script src="../lib/Kanvas/kanvas.js"></script>
@ -28,9 +32,6 @@
<script src="../swf/shape.js"></script>
<script src="../swf/text.js"></script>
<script src="../swf/prototypes.js"></script>
<!-- Load AVM1 Dependencies -->
<script src="../avm1/classes.js"></script>
<script src="../avm1/globals.js"></script>
@ -39,22 +40,90 @@
<script src="../swf/embed.js"></script>
<script src="../swf/renderer.js"></script>
<!-- Load AVM2 Dependencies -->
<script src="../avm2/util.js"></script>
<script src="../avm2/options.js"></script>
<script src="../avm2/metrics.js"></script>
<script>
var Counter = new metrics.Counter(true);
var Timer = metrics.Timer;
var Option = options.Option;
var OptionSet = options.OptionSet;
var systemOptions = new OptionSet("System Options");
var disassemble = systemOptions.register(new Option("d", "disassemble", "boolean", false, "disassemble"));
var traceLevel = systemOptions.register(new Option("t", "traceLevel", "number", 0, "trace level"));
window.print = function(s) {
console.log(s);
};
</script>
<script src="../avm2/constants.js"></script>
<script src="../avm2/errors.js"></script>
<script src="../avm2/opcodes.js"></script>
<script src="../avm2/parser.js"></script>
<script src="../avm2/analyze.js"></script>
<script src="../avm2/compiler/lljs/src/estransform.js"></script>
<script src="../avm2/compiler/lljs/src/escodegen.js"></script>
<script src="../avm2/compiler/inferrer.js"></script>
<script src="../avm2/compiler/compiler.js"></script>
<script src="../avm2/domain.js"></script>
<script src="../avm2/runtime.js"></script>
<script src="../avm2/native.js"></script>
<script src="../avm2/disassembler.js"></script>
<script src="../avm2/interpreter.js"></script>
<script src="../avm2/vm.js"></script>
<script src="avm2utils.js"></script>
<!-- Load Flash Dependencies -->
<script src="../flash/util.js"></script>
<script src="../flash/events/EventPhase.js"></script>
<script src="../flash/events/Event.js"></script>
<script src="../flash/events/ProgressEvent.js"></script>
<script src="../flash/events/EventDispatcher.js"></script>
<!-- Autogenerated flash references: base=../flash/ -->
<script src="../flash/display/Bitmap.js"></script>
<script src="../flash/display/BitmapData.js"></script>
<script src="../flash/display/DisplayObject.js"></script>
<script src="../flash/display/InteractiveObject.js"></script>
<script src="../flash/display/DisplayObjectContainer.js"></script>
<script src="../flash/display/Graphics.js"></script>
<script src="../flash/display/Sprite.js"></script>
<script src="../flash/display/InteractiveObject.js"></script>
<script src="../flash/display/Loader.js"></script>
<script src="../flash/display/LoaderInfo.js"></script>
<script src="../flash/display/MorphShape.js"></script>
<script src="../flash/display/MovieClip.js"></script>
<script src="../flash/display/Shape.js"></script>
<script src="../flash/display/SimpleButton.js"></script>
<script src="../flash/display/Sprite.js"></script>
<script src="../flash/display/Stage.js"></script>
<script src="../flash/events/Event.js"></script>
<script src="../flash/events/EventDispatcher.js"></script>
<script src="../flash/events/KeyboardEvent.js"></script>
<script src="../flash/events/MouseEvent.js"></script>
<script src="../flash/events/TextEvent.js"></script>
<script src="../flash/events/TimerEvent.js"></script>
<script src="../flash/external/ExternalInterface.js"></script>
<script src="../flash/geom/ColorTransform.js"></script>
<script src="../flash/geom/Matrix.js"></script>
<script src="../flash/geom/Point.js"></script>
<script src="../flash/geom/Rectangle.js"></script>
<script src="../flash/geom/Transform.js"></script>
<script src="../flash/media/Sound.js"></script>
<script src="../flash/media/SoundMixer.js"></script>
<script src="../flash/media/SoundTransform.js"></script>
<script src="../flash/media/Video.js"></script>
<script src="../flash/net/NetConnection.js"></script>
<script src="../flash/net/NetStream.js"></script>
<script src="../flash/net/Responder.js"></script>
<script src="../flash/net/URLRequest.js"></script>
<script src="../flash/system/Capabilities.js"></script>
<script src="../flash/system/FSCommand.js"></script>
<script src="../flash/text/Font.js"></script>
<script src="../flash/text/StaticText.js"></script>
<script src="../flash/text/TextField.js"></script>
<script src="../flash/ui/Keyboard.js"></script>
<script src="../flash/ui/Mouse.js"></script>
<script src="../flash/utils/Timer.js"></script>
<!-- Autogenerated flash references end -->
<script src="../flash/stubs.js"></script>
<script>
// Extenstion communication object... as it used in pdf.js
@ -151,29 +220,41 @@
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 });
});
}
</script>
<style>
#viewer {
position:fixed;left:0;top:0;bottom:0;right:0;
background-color:magenta;
body {
margin: 0;
overflow: hidden;
}
#viewer {
position:fixed;
left:0;top:0;bottom:0;right:0;
overflow: hidden;
/* background-color:magenta; */
}
#fallback {
display: none;
}
#fallback.enabled {
display: block;
position:fixed; right: 10px; bottom: 10px; width: 70px; height: 14px;
position:fixed;
right: 10px; bottom: 10px; width: 70px; height: 16px;
color: white;
background-color: #400040;
background-color: #0b3268;
font: bold 10px sans-serif;
text-align: center;
text-decoration: none;
border-radius: 5px;
box-shadow: 0px 0px 3px 3px #888;
box-shadow: 0px 0px 2px 2px #888;
}
#fallback .icon {
display: inline-block;
@ -184,6 +265,6 @@
<body onload="runViewer()">
<div id="viewer"></div>
<a id="fallback" href="#">shumway <span class="icon">&times;</span></a>
<a id="fallback" href="#">Shumway <span class="icon">&times;</span></a>
</body>
</html>

Просмотреть файл

@ -5,16 +5,16 @@
<Description about="urn:mozilla:install-manifest">
<em:id>shumway@research.mozilla.org</em:id>
<em:name>shumway</em:name>
<em:version>0.2.1</em:version>
<em:name>Shumway</em:name>
<em:version>(SHUMWAY_VERSION)</em:version>
<em:iconURL>chrome://shumway/skin/logo.png</em:iconURL>
<!-- Firefox -->
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>10.0</em:minVersion>
<em:maxVersion>17.0a1</em:maxVersion>
<em:minVersion>17.0</em:minVersion>
<em:maxVersion>19.0a1</em:maxVersion>
</Description>
</em:targetApplication>
@ -22,16 +22,18 @@
<em:targetApplication>
<Description>
<em:id>{aa3c5121-dab2-40e2-81ca-7ea25febc110}</em:id>
<em:minVersion>10.0</em:minVersion>
<em:maxVersion>17.0a1</em:maxVersion>
<em:minVersion>17.0</em:minVersion>
<em:maxVersion>19.0a1</em:maxVersion>
</Description>
</em:targetApplication>
<em:bootstrap>true</em:bootstrap>
<em:unpack>true</em:unpack>
<em:creator>Mozilla Research</em:creator>
<em:description>shumway loader</em:description>
<em:description>Shumway is an HTML5 technology experiment that explores building a faithful and efficient renderer for the SWF file format without native code assistance.</em:description>
<em:homepageURL>https://github.com/mozilla/shumway/</em:homepageURL>
<em:type>2</em:type>
<!-- Use the raw link for updates so we we can use SSL. -->
<em:updateURL>https://github.com/mozilla/shumway/raw/gh-pages/extension/firefox/update.rdf</em:updateURL>
</Description>
</RDF>

Просмотреть файл

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<RDF:Description about="urn:mozilla:extension:shumway@research.mozilla.org">
<em:updates>
<RDF:Seq>
<RDF:li>
<RDF:Description>
<em:version>(SHUMWAY_VERSION)</em:version>
<em:targetApplication>
<RDF:Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>17.0</em:minVersion>
<em:maxVersion>19.0a1</em:maxVersion>
<!-- Use the raw link for updates so we we can use SSL. -->
<em:updateLink>https://github.com/mozilla/shumway/raw/gh-pages/extension/firefox/shumway.xpi</em:updateLink>
</RDF:Description>
</em:targetApplication>
</RDF:Description>
</RDF:li>
</RDF:Seq>
</em:updates>
</RDF:Description>
</RDF:RDF>

Просмотреть файл

@ -23,10 +23,10 @@
var nativeCanvasProto = nativeCanvasClass.prototype;
var native2dContextProto = native2dContextClass.prototype;
var kanvas2dContextProto = Object.create(native2dContextProto);
var matrixClass;
var pathClass;
var wrap2dContext;
var shimCurrentTransform = !('currentTransform' in native2dContext);
var shimPath = typeof Path === 'undefined';
@ -44,7 +44,7 @@
val = desc.get.call(this);
defineProperty(this, prop, {
value: val,
writable: desc.writable,
writable: true, // some browsers need that to be true
configurable: desc.configurable,
enumerable: desc.enumerable
});
@ -74,8 +74,7 @@
var context;
if (contextId === 'kanvas-2d') {
context = nativeGetContext.call(this, '2d');
context.__proto__ = kanvas2dContextProto;
context = wrap2dContext(nativeGetContext.call(this, '2d'));
} else {
context = nativeGetContext.apply(this, arguments);
}
@ -87,15 +86,17 @@
};
try {
var matrix = new SVGMatrix;
matrixClass = matrix.constructor;
} catch (err) {
if (typeof SVGMatrix !== 'undefined')
matrixClass = (new SVGMatrix).constructor;
} catch (err) { }
if (!matrixClass) {
var svgNamespace = 'http://www.w3.org/2000/svg';
var svgElement = document.createElementNS(svgNamespace, 'svg');
matrixClass = function SVGMatrix() {
return svgElement.createSVGMatrix();
}
};
matrixClass.prototype = SVGMatrix.prototype;
}
@ -105,8 +106,11 @@
return new Path(d);
var displayList = [];
var hitCanvas = nativeCanvas.cloneNode();
var hitCanvas = document.createElement('canvas');
hitCanvas.width = hitCanvas.height = 1;
var hitContext = hitCanvas.getContext('2d');
var pathState = [Number.MAX_VALUE, 0, Number.MAX_VALUE, 0];
defineProperties(this, {
@ -225,7 +229,7 @@
defineLazyProperty(pathProto, '__draw__', {
get: function () {
return Function('c', this.__displayList__.join(';'));
return new Function('c', this.__displayList__.join(';'));
}
});
@ -240,19 +244,30 @@
pathClass.prototype = pathProto;
['fill', 'stroke', 'clip'].forEach(function (methodName) {
var nativeMethod = kanvas2dContextProto[methodName];
kanvas2dContextProto[methodName] = function (path) {
wrap2dContext = (function () {
function wrapNativeMethod(nativeMethod, pathClass) {
return function wrappedMethod(path) {
if (path instanceof pathClass) {
this.beginPath();
path.__draw__(this);
}
nativeMethod.call(this);
};
});
}
var wrappedFillMethod = wrapNativeMethod(native2dContextProto.fill, pathClass);
var wrappedStrokeMethod = wrapNativeMethod(native2dContextProto.stroke, pathClass);
var wrappedClipMethod = wrapNativeMethod(native2dContextProto.clip, pathClass);
return function wrap2dContext(ctx) {
ctx.fill = wrappedFillMethod;
ctx.stroke = wrappedStrokeMethod;
ctx.clip = wrappedClipMethod;
return ctx;
};
})();
} else {
pathClass = Path;
wrap2dContext = function(ctx) { return ctx; };
}
Kanvas.SVGMatrix = matrixClass;

1
lib/xstats Submodule

@ -0,0 +1 @@
Subproject commit b00277ea4a733145e01cb68c159d689f703ab2aa

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -32,23 +32,29 @@ AS2Globals.prototype = {
nativeTarget.duplicateMovieClip(newname, depth);
},
fscommand: function (command, parameters) {
flash.system.fscommand.apply(null, arguments);
var fscommand = avm2.applicationDomain.getProperty(
Multiname.fromSimpleName('flash.system.fscommand'), true, true);
fscommand.apply(null, arguments);
},
getProperty: function(target, index) {
var nativeTarget = AS2Context.instance.resolveTarget(target);
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);
var request = new flash.net.URLRequest(url);
if (method)
request.method = method;
flash.net.navigateToURL(request, target);
var navigateToURL = avm2.applicationDomain.getProperty(
Multiname.fromSimpleName('flash.net.navigateToURL'), true, true);
navigateToURL(request, target);
},
getVersion: function() {
return flash.system.Capalilities.version;
return flash.system.Capabilities.version;
},
gotoAndPlay: function() {
var nativeTarget = AS2Context.instance.resolveTarget();
@ -83,11 +89,19 @@ AS2Globals.prototype = {
},
loadMovie: function(url, target, method) {
var nativeTarget = AS2Context.instance.resolveTarget(target);
// some swfs are using loadMovie to call fscommmand
if (/^fscommand:/i.test(url))
return this.fscommand(url.substring('fscommand:'.length), target);
// flash.display.Loader, flash.net.URLLoader
throw 'Not implemented: loadMovie';
},
loadMovieNum: function(url, level, method) {
var nativeTarget = AS2Context.instance.resolveLevel(level);
// some swfs are using loadMovieNum to call fscommmand
if (/^fscommand:/i.test(url))
return this.fscommand(url.substring('fscommand:'.length));
// flash.display.Loader, flash.net.URLLoader
throw 'Not implemented: loadMovieNum';
},
@ -179,7 +193,8 @@ AS2Globals.prototype = {
nativeTarget.stop();
},
stopAllSounds: function() {
flash.media.SoundMixer.stopAll();
var soundMixerClass = avm2.systemDomain.getClass("flash.media.SoundMixer");
soundMixerClass.native.static.stopAll();
},
stopDrag: function(target) {
var nativeTarget = AS2Context.instance.resolveTarget(target);
@ -190,15 +205,16 @@ AS2Globals.prototype = {
},
targetPath: function(target) {
var nativeTarget = AS2Context.instance.resolveTarget(target);
// nativeTarget.getPath() ?
throw 'Not implemented: targetPath';
return nativeTarget._target;
},
toggleHighQuality: function() {
// flash.display.Stage.quality
throw 'Not implemented: toggleHighQuality';
},
trace: function(expression) {
console.log(expression);
var trace = avm2.applicationDomain.getProperty(
Multiname.fromSimpleName('trace'), true, true);
trace(expression);
},
unloadMovie: function(target) {
var nativeTarget = AS2Context.instance.resolveTarget(target);
@ -234,6 +250,7 @@ AS2Globals.prototype = {
AsBroadcaster: AS2Broadcaster,
Stage: AS2Stage,
Button: AS2Button,
TextField: AS2TextField,
Rectangle: AS2Rectangle,
Key: AS2Key,
Mouse: AS2Mouse

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- mode: javascript; tab-width: 4; insert-tabs-mode: nil; indent-tabs-mode: nil -*- */
/* -*- mode: javascript; tab-width: 4; indent-tabs-mode: nil -*- */
var isAVM1TraceEnabled = false;
@ -17,9 +17,17 @@ function AS2Context(swfVersion) {
this.globals = new AS2Globals(this);
var windowScope = new AS2ScopeListItem(window, null);
this.initialScope = new AS2ScopeListItem(this.globals, windowScope);
this.assets = {};
}
AS2Context.instance = null;
AS2Context.prototype = {
addAssets: function(assets) {
for (var i = 0; i < assets.length; i++) {
if (assets[i].className) {
this.assets[assets[i].className] = assets[i];
}
}
},
resolveTarget: function(target) {
if (!target)
target = this.defaultTarget;
@ -35,7 +43,128 @@ AS2Context.prototype = {
}
};
function executeActions(actionsData, context, scope) {
function as2GetType(v) {
if (v === null)
return 'null';
var type = typeof v;
if (type === 'function')
return 'object';
if (type === 'object' && v instanceof AS2MovieClip)
return 'movieclip';
return type;
}
function as2ToPrimitive(value) {
return as2GetType(value) !== 'object' ? value : value.valueOf();
}
function as2ToAddPrimitive(value) {
if (as2GetType(value) !== 'object')
return value;
if (value instanceof Date && AS2Context.instance.swfVersion >= 6) {
return value.toString();
} else {
return value.valueOf();
}
}
function as2ToBoolean(value) {
switch (as2GetType(value)) {
case 'undefined':
case 'null':
default:
return false;
case 'boolean':
return value;
case 'number':
return value != 0 && !isNaN(value);
case 'string':
return value.length !== 0;
case 'object':
return true;
}
}
function as2ToNumber(value) {
value = as2ToPrimitive(value);
switch (as2GetType(value)) {
case 'undefined':
case 'null':
return AS2Context.instance.swfVersion >= 7 ? NaN : 0;
default:
return AS2Context.instance.swfVersion >= 5 ? NaN : 0;
case 'null':
return NaN;
case 'boolean':
return value ? 1 : +0;
case 'number':
return value;
case 'string':
if (value === '' && AS2Context.instance.swfVersion < 5)
return 0;
return +value;
}
}
function as2ToInteger(value) {
var result = as2ToNumber(value);
if (isNaN(result))
return 0;
if (!isFinite(result) || result == 0)
return result;
return (result < 0 ? -1 : 1) * Math.floor(Math.abs(result));
}
function as2ToInt32(value) {
var result = as2ToNumber(value);
return (isNaN(result) || !isFinite(result) || result == 0) ? 0 :
(result | 0);
}
function as2ToString(value) {
switch (as2GetType(value)) {
case 'undefined':
return AS2Context.instance.swfVersion >= 7 ? 'undefined' : '';
case 'null':
return 'null';
case 'boolean':
return value ? 'true' : 'false';
case 'number':
return value.toString();
case 'string':
return value;
case 'undefined':
return 'undefined';
case 'movieclip':
return value.$targetPath;
case 'object':
var result = value.toString !== Function.prototype.toString ?
value.toString() : value;
if (typeof result === 'string')
return result;
return typeof value === 'function' ? '[type Function]'
: '[type Object]';
}
}
function as2Compare(x, y) {
var x2 = as2ToPrimitive(x);
var y2 = as2ToPrimitive(y);
if (typeof x2 === 'string' && typeof y2 === 'string') {
return x2 < y2;
} else {
return as2ToNumber(x2) < as2ToNumber(y2);
}
}
function as2InstanceOf(obj, constructor) {
if (obj instanceof constructor)
return true;
// TODO interface check
return false;
}
function executeActions(actionsData, context, scope, assets) {
var actionTracer = ActionTracerFactory.get();
var scopeContainer = context.initialScope.create(scope);
@ -43,6 +172,9 @@ function executeActions(actionsData, context, scope) {
try {
AS2Context.instance = context;
context.defaultTarget = scope;
context.globals['this'] = scope;
if (assets)
context.addAssets(assets);
actionTracer.message('ActionScript Execution Starts');
actionTracer.indent();
interpretActions(actionsData, scopeContainer, null, []);
@ -53,6 +185,26 @@ function executeActions(actionsData, context, scope) {
}
}
function lookupAS2Children(targetPath, defaultTarget, root) {
var path = targetPath.split('/');
if (path[path.length - 1] === '') {
path.pop();
}
var obj = defaultTarget;
if (path[0] === '') {
defaultTarget = root;
path.shift();
}
while (path.length > 0) {
obj = obj.$lookupChild(path[0]);
if (!obj) {
throw path[0] + ' is undefined in ' + targetPath;
}
path.shift();
}
return obj;
}
function interpretActions(actionsData, scopeContainer,
constantPool, registers) {
var currentContext = AS2Context.instance;
@ -61,7 +213,7 @@ function interpretActions(actionsData, scopeContainer,
if (!targetPath)
defaultTarget = _global._root;
else
defaultTarget = defaultTarget.$lookupChild(targetPath);
defaultTarget = lookupAS2Children(targetPath, defaultTarget, _global._root);
currentContext.defaultTarget = defaultTarget;
}
@ -133,21 +285,12 @@ function interpretActions(actionsData, scopeContainer,
}
return false;
}
function instanceOf(obj, constructor) {
if (obj instanceof constructor)
return true;
// TODO interface check
return false;
}
function isMovieClip(obj) {
return instanceOf(obj, _global.MovieClip);
}
function resolveVariableName(variableName) {
var obj, name;
if (variableName.indexOf(':') >= 0) {
// "/A/B:FOO references the FOO variable in the movie clip with a target path of /A/B."
var parts = variableName.split(':');
var obj = defaultTarget.$lookupChild(parts[0]);
var obj = lookupAS2Children(parts[0], defaultTarget, _global._root);
name = parts[1];
} else if (variableName.indexOf('.') >= 0) {
// new object reference
@ -156,10 +299,11 @@ function interpretActions(actionsData, scopeContainer,
var obj = _global;
for (var i = 0; i < objPath.length; i++) {
obj = obj[objPath[i]];
if (!obj)
if (!obj) {
throw objPath.slice(0, i + 1) + ' is undefined';
}
}
}
if(!obj)
return; // local variable
@ -176,6 +320,10 @@ function interpretActions(actionsData, scopeContainer,
if (target)
return target.obj[target.name];
var mc = defaultTarget.$lookupChild(variableName);
if (mc)
return mc;
for (var p = scopeContainer; p; p = p.next) {
if (variableName in p.scope) {
return p.scope[variableName];
@ -194,8 +342,8 @@ function interpretActions(actionsData, scopeContainer,
target.obj[target.name] = value;
return;
}
scope[variableName] = value;
var _this = scope.this || getVariable('this');
_this[variableName] = value;
}
function getFunction(functionName) {
var fn = getVariable(functionName);
@ -238,18 +386,29 @@ function interpretActions(actionsData, scopeContainer,
var scope = scopeContainer.scope;
var isSwfVersion5 = currentContext.swfVersion >= 5;
var actionTracer = ActionTracerFactory.get();
var nextPosition;
function skipActions(count) {
while (count > 0 && stream.position < stream.end) {
var actionCode = stream.readUI8();
var length = actionCode >= 0x80 ? stream.readUI16() : 0;
stream.position += length;
count--;
}
nextPosition = stream.position;
}
while (stream.position < stream.end) {
var actionCode = stream.readUI8();
var length = actionCode >= 0x80 ? stream.readUI16() : 0;
var nextPosition = stream.position + length;
nextPosition = stream.position + length;
actionTracer.print(stream.position, actionCode, stack);
switch (actionCode) {
// SWF 3 actions
case 0x81: // ActionGotoFrame
var frame = stream.readUI16();
_global.gotoAndPlay(frame);
_global.gotoAndPlay(frame + 1);
break;
case 0x83: // ActionGetURL
var urlString = stream.readString();
@ -278,7 +437,7 @@ function interpretActions(actionsData, scopeContainer,
var frame = stream.readUI16();
var skipCount = stream.readUI8();
if (!_global.ifFrameLoaded(frame))
nextPosition += skipCount; // actions or bytes ?
skipActions(skipCount);
break;
case 0x8B: // ActionSetTarget
var targetName = stream.readString();
@ -334,86 +493,85 @@ function interpretActions(actionsData, scopeContainer,
stack.pop();
break;
case 0x0A: // ActionAdd
var a = +stack.pop();
var b = +stack.pop();
var a = as2ToNumber(stack.pop());
var b = as2ToNumber(stack.pop());
stack.push(a + b);
break;
case 0x0B: // ActionSubtract
var a = +stack.pop();
var b = +stack.pop();
var a = as2ToNumber(stack.pop());
var b = as2ToNumber(stack.pop());
stack.push(b - a);
break;
case 0x0C: // ActionMultiply
var a = +stack.pop();
var b = +stack.pop();
var a = as2ToNumber(stack.pop());
var b = as2ToNumber(stack.pop());
stack.push(a * b);
break;
case 0x0D: // ActionDivide
var a = +stack.pop();
var b = +stack.pop();
var a = as2ToNumber(stack.pop());
var b = as2ToNumber(stack.pop());
var c = b / a;
stack.push(isSwfVersion5 ? c : isFinite(c) ? c : '#ERROR#');
break;
case 0x0E: // ActionEquals
var a = +stack.pop();
var b = +stack.pop();
var a = as2ToNumber(stack.pop());
var b = as2ToNumber(stack.pop());
var f = a == b;
stack.push(isSwfVersion5 ? f : f ? 1 : 0);
break;
case 0x0F: // ActionLess
var a = +stack.pop();
var b = +stack.pop();
var a = as2ToNumber(stack.pop());
var b = as2ToNumber(stack.pop());
var f = b < a;
stack.push(isSwfVersion5 ? f : f ? 1 : 0);
break;
case 0x10: // ActionAnd
var a = stack.pop();
var b = stack.pop();
var a = as2ToBoolean(stack.pop());
var b = as2ToBoolean(stack.pop());
var f = a && b;
stack.push(isSwfVersion5 ? f : f ? 1 : 0);
break;
case 0x11: // ActionOr
var a = stack.pop();
var b = stack.pop();
var a = as2ToBoolean(stack.pop());
var b = as2ToBoolean(stack.pop());
var f = a || b;
stack.push(isSwfVersion5 ? f : f ? 1 : 0);
break;
case 0x12: // ActionNot
var f = !stack.pop();
var f = !as2ToBoolean(stack.pop());
stack.push(isSwfVersion5 ? f : f ? 1 : 0);
break;
case 0x13: // ActionStringEquals
var sa = '' + stack.pop();
var sb = '' + stack.pop();
var sa = as2ToString(stack.pop());
var sb = as2ToString(stack.pop());
var f = sa == sb;
stack.push(isSwfVersion5 ? f : f ? 1 : 0);
break;
case 0x14: // ActionStringLength
case 0x31: // ActionMBStringLength
stack.push(_global.length(stack.pop()));
var sa = '' + stack.pop();
stack.push(sa.length);
var sa = as2ToString(stack.pop());
stack.push(_global.length(sa));
break;
case 0x21: // ActionStringAdd
var sa = '' + stack.pop();
var sb = '' + stack.pop();
var sa = as2ToString(stack.pop());
var sb = as2ToString(stack.pop());
stack.push(sb + sa);
break;
case 0x15: // ActionStringExtract
var count = stack.pop();
var index = stack.pop();
var value = stack.pop();
var value = as2ToString(stack.pop());
stack.push(_global.substring(value, index, count));
break;
case 0x35: // ActionMBStringExtract
var count = stack.pop();
var index = stack.pop();
var value = stack.pop();
var value = as2ToString(stack.pop());
stack.push(_global.mbsubstring(value, index, count));
break;
case 0x29: // ActionStringLess
var sa = '' + stack.pop();
var sb = '' + stack.pop();
var sa = as2ToString(stack.pop());
var sb = as2ToString(stack.pop());
var f = sb < sa;
stack.push(isSwfVersion5 ? f : f ? 1 : 0);
break;
@ -529,9 +687,7 @@ function interpretActions(actionsData, scopeContainer,
var skipCount = stream.readUI8();
var frame = stack.pop();
if (!_global.ifFrameLoaded(frame))
nextPosition += skipCount; // actions or bytes ?
debugger;
//_global.waitForFrame(label, skipCount);
skipActions(skipCount);
break;
case 0x26: // ActionTrace
var value = stack.pop();
@ -654,15 +810,23 @@ function interpretActions(actionsData, scopeContainer,
var args = [];
for (var i = 0; i < numArgs; i++)
args.push(stack.pop());
var result = {};
var method;
if (methodName) {
if (!(methodName in obj))
throw 'Method ' + methodName + ' is not defined.';
obj[methodName].apply(result, args);
} else
obj.apply(result, args);
method = obj[methodName];
} else {
method = obj;
}
// XXX: this is non-semantics-preserving, but it's
// necessary to make constructors for runtime objects
// work.
var result = new (method.bind.apply(method, [null].concat(args)))();
if (!result) {
result = {};
result.constructor = method;
method.apply(result, args);
}
stack.push(result);
break;
case 0x40: // ActionNewObject
@ -689,7 +853,7 @@ function interpretActions(actionsData, scopeContainer,
break;
case 0x45: // ActionTargetPath
var obj = stack.pop();
stack.push(isMovieClip(obj) ? obj.getTargetPath() : void(0));
stack.push(as2GetType(obj) === 'movieclip' ? obj._target : void(0));
break;
case 0x94: // ActionWith
var codeSize = stream.readUI16();
@ -698,68 +862,73 @@ function interpretActions(actionsData, scopeContainer,
processWith(obj, stream.readBytes(codeSize));
break;
case 0x4A: // ActionToNumber
stack.push(+stack.pop());
stack.push(as2ToNumber(stack.pop()));
break;
case 0x4B: // ActionToString
stack.push("" + stack.pop());
stack.push(as2ToString(stack.pop()));
break;
case 0x44: // ActionTypeOf
var obj = stack.pop();
var result = isMovieClip(obj) ? 'movieclip' : typeof obj;
var result = as2GetType(obj);
stack.push(result);
break;
case 0x47: // ActionAdd2
var arg1 = stack.pop();
var arg2 = stack.pop();
stack.push(arg2 + arg1);
var sb = as2ToAddPrimitive(arg1);
var sa = as2ToAddPrimitive(arg2);
if (typeof sa === 'string' || typeof sb === 'string')
stack.push(as2ToString(sa) + as2ToString(sb));
else
stack.push(as2ToNumber(sa) + as2ToNumber(sb));
break;
case 0x48: // ActionLess2
var arg1 = stack.pop();
var arg2 = stack.pop();
stack.push(arg2 < arg1);
stack.push(as2Compare(arg2, arg1));
break;
case 0x3F: // ActionModulo
var arg1 = stack.pop();
var arg2 = stack.pop();
var arg1 = as2ToNumber(stack.pop());
var arg2 = as2ToNumber(stack.pop());
stack.push(arg2 % arg1);
break;
case 0x60: // ActionBitAnd
var arg1 = stack.pop();
var arg2 = stack.pop();
var arg1 = as2ToInt32(stack.pop());
var arg2 = as2ToInt32(stack.pop());
stack.push(arg2 & arg1);
break;
case 0x63: // ActionBitLShift
var arg1 = stack.pop();
var arg2 = stack.pop();
var arg1 = as2ToInt32(stack.pop());
var arg2 = as2ToInt32(stack.pop());
stack.push(arg2 << arg1);
break;
case 0x61: // ActionBitOr
var arg1 = stack.pop();
var arg2 = stack.pop();
var arg1 = as2ToInt32(stack.pop());
var arg2 = as2ToInt32(stack.pop());
stack.push(arg2 | arg1);
break;
case 0x64: // ActionBitRShift
var arg1 = stack.pop();
var arg2 = stack.pop();
var arg1 = as2ToInt32(stack.pop());
var arg2 = as2ToInt32(stack.pop());
stack.push(arg2 >> arg1);
break;
case 0x65: // ActionBitURShift
var arg1 = stack.pop();
var arg2 = stack.pop();
var arg1 = as2ToInt32(stack.pop());
var arg2 = as2ToInt32(stack.pop());
stack.push(arg2 >>> arg1);
break;
case 0x62: // ActionBitXor
var arg1 = stack.pop();
var arg2 = stack.pop();
var arg1 = as2ToInt32(stack.pop());
var arg2 = as2ToInt32(stack.pop());
stack.push(arg2 ^ arg1);
break;
case 0x51: // ActionDecrement
var arg1 = stack.pop();
var arg1 = as2ToNumber(stack.pop());
arg1--;
stack.push(arg1);
break;
case 0x50: // ActionIncrement
var arg1 = stack.pop();
var arg1 = as2ToNumber(stack.pop());
arg1++;
stack.push(arg1);
break;
@ -779,7 +948,7 @@ function interpretActions(actionsData, scopeContainer,
case 0x54: // ActionInstanceOf
var constr = stack.pop();
var obj = stack.pop();
stack.push(instanceOf(Object(obj), constr));
stack.push(as2InstanceOf(Object(obj), constr));
break;
case 0x55: // ActionEnumerate2
var obj = stack.pop();
@ -795,11 +964,11 @@ function interpretActions(actionsData, scopeContainer,
case 0x67: // ActionGreater
var arg1 = stack.pop();
var arg2 = stack.pop();
stack.push(arg2 > arg1);
stack.push(as2Compare(arg1, arg2));
break;
case 0x68: // ActionStringGreater
var sa = '' + stack.pop();
var sb = '' + stack.pop();
var sa = as2ToString(stack.pop());
var sb = as2ToString(stack.pop());
var f = sb > sa;
stack.push(isSwfVersion5 ? f : f ? 1 : 0);
break;
@ -859,7 +1028,7 @@ function interpretActions(actionsData, scopeContainer,
case 0x2B: // ActionCastOp
var obj = stack.pop();
var constr = stack.pop();
stack.push(instanceOf(obj, constr) ? obj : null);
stack.push(as2InstanceOf(obj, constr) ? obj : null);
break;
case 0x2C: // ActionImplementsOp
var constr = stack.pop();

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- mode: javascript; tab-width: 4; insert-tabs-mode: nil; indent-tabs-mode: nil -*- */
/* -*- mode: javascript; tab-width: 4; indent-tabs-mode: nil -*- */
var fs = require('fs');

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- mode: javascript; tab-width: 4; insert-tabs-mode: nil; indent-tabs-mode: nil -*- */
/* -*- mode: javascript; tab-width: 4; indent-tabs-mode: nil -*- */
var expect = require('expect.js');
require('./domstubs.js');

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- mode: javascript; tab-width: 4; insert-tabs-mode: nil; indent-tabs-mode: nil -*- */
/* -*- mode: javascript; tab-width: 4; indent-tabs-mode: nil -*- */
var expect = require('expect.js');
require('./domstubs.js');

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- mode: javascript; tab-width: 4; insert-tabs-mode: nil; indent-tabs-mode: nil -*- */
/* -*- mode: javascript; tab-width: 4; indent-tabs-mode: nil -*- */
var expect = require('expect.js');
require('./domstubs.js');

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- mode: javascript; tab-width: 4; insert-tabs-mode: nil; indent-tabs-mode: nil -*- */
/* -*- mode: javascript; tab-width: 4; indent-tabs-mode: nil -*- */
var expect = require('expect.js');
require('../stream.js');

Просмотреть файл

@ -1,17 +1,17 @@
var Control = (function () {
const SEQ = 1;
const LOOP = 2;
const IF = 3;
const CASE = 4;
const SWITCH = 5;
const LABEL_CASE = 6;
const LABEL_SWITCH = 7;
const EXIT = 8;
const BREAK = 9;
const CONTINUE = 10;
const TRY = 11;
const CATCH = 12;
var SEQ = 1;
var LOOP = 2;
var IF = 3;
var CASE = 4;
var SWITCH = 5;
var LABEL_CASE = 6;
var LABEL_SWITCH = 7;
var EXIT = 8;
var BREAK = 9;
var CONTINUE = 10;
var TRY = 11;
var CATCH = 12;
function Seq(body) {
this.kind = SEQ;
@ -398,9 +398,9 @@ var Analysis = (function () {
function blockSetClass(length, blockById) {
var BlockSet = BitSetFunctor(length);
const ADDRESS_BITS_PER_WORD = BlockSet.ADDRESS_BITS_PER_WORD;
const BITS_PER_WORD = BlockSet.BITS_PER_WORD;
const BIT_INDEX_MASK = BlockSet.BIT_INDEX_MASK;
var ADDRESS_BITS_PER_WORD = BlockSet.ADDRESS_BITS_PER_WORD;
var BITS_PER_WORD = BlockSet.BITS_PER_WORD;
var BIT_INDEX_MASK = BlockSet.BIT_INDEX_MASK;
BlockSet.singleton = function singleton(b) {
var bs = new BlockSet();
@ -867,9 +867,9 @@ var Analysis = (function () {
// The root must not have preds!
release || assert(root.preds.length === 0);
const ONCE = 1;
const BUNCH_OF_TIMES = 2;
const BlockSet = this.BlockSet;
var ONCE = 1;
var BUNCH_OF_TIMES = 2;
var BlockSet = this.BlockSet;
var blocks = [];
var visited = {};
@ -1014,7 +1014,7 @@ var Analysis = (function () {
},
computeFrontiers: function computeFrontiers() {
const BlockSet = this.BlockSet;
var BlockSet = this.BlockSet;
var blocks = this.blocks;
for (var b = 0, n = blocks.length; b < n; b++) {
@ -1055,7 +1055,7 @@ var Analysis = (function () {
return false;
}
const BlockSet = this.BlockSet;
var BlockSet = this.BlockSet;
//
// Find all SCCs at or below the level of some root that are not already
@ -1206,8 +1206,8 @@ var Analysis = (function () {
},
induceControlTree: function induceControlTree() {
const hasExceptions = this.method.exceptions.length > 0;
const BlockSet = this.BlockSet;
var hasExceptions = this.method.exceptions.length > 0;
var BlockSet = this.BlockSet;
function maybe(exit, save) {
exit.recount();

Просмотреть файл

@ -29,23 +29,23 @@ var escodegen = require(__dirname + "/../compiler/lljs/src/escodegen.js");
var estransform = require(__dirname + "/../compiler/lljs/src/estransform.js");
// Import nodes
const T = estransform;
const Node = T.Node;
const Literal = T.Literal;
const Identifier = T.Identifier;
const CallExpression = T.CallExpression;
const ExpressionStatement = T.ExpressionStatement;
const FunctionExpression = T.FunctionExpression;
const FunctionDeclaration = T.FunctionDeclaration;
const MemberExpression = T.MemberExpression;
const AssignmentExpression = T.AssignmentExpression;
const BlockStatement = T.BlockStatement;
const VariableDeclaration = T.VariableDeclaration;
const VariableDeclarator = T.VariableDeclarator;
const ArrayExpression = T.ArrayExpression;
const BinaryExpression = T.BinaryExpression;
const ObjectExpression = T.ObjectExpression;
const Property = T.Property;
var T = estransform;
var Node = T.Node;
var Literal = T.Literal;
var Identifier = T.Identifier;
var CallExpression = T.CallExpression;
var ExpressionStatement = T.ExpressionStatement;
var FunctionExpression = T.FunctionExpression;
var FunctionDeclaration = T.FunctionDeclaration;
var MemberExpression = T.MemberExpression;
var AssignmentExpression = T.AssignmentExpression;
var BlockStatement = T.BlockStatement;
var VariableDeclaration = T.VariableDeclaration;
var VariableDeclarator = T.VariableDeclarator;
var ArrayExpression = T.ArrayExpression;
var BinaryExpression = T.BinaryExpression;
var ObjectExpression = T.ObjectExpression;
var Property = T.Property;
// Parse arguments

Просмотреть файл

@ -241,7 +241,7 @@ function shortPath(str, length) {
function extractData(str) {
var lines = str.replace(/\r/g, "").split("\n");
var data = {};
const jsonPrefix = "SHUMWAY$JSON";
var jsonPrefix = "SHUMWAY$JSON";
var textLines = lines.filter(function (x) {
if (x.indexOf(jsonPrefix) === 0) {
var lineData = {};

Просмотреть файл

@ -21,43 +21,43 @@ function shouldCompile(mi) {
return true;
}
const T = estransform;
var T = estransform;
const Literal = T.Literal;
const Identifier = T.Identifier;
const VariableDeclaration = T.VariableDeclaration;
const VariableDeclarator = T.VariableDeclarator;
const MemberExpression = T.MemberExpression;
const BinaryExpression = T.BinaryExpression;
const SequenceExpression = T.SequenceExpression;
const CallExpression = T.CallExpression;
const AssignmentExpression = T.AssignmentExpression;
const ExpressionStatement = T.ExpressionStatement;
const ReturnStatement = T.ReturnStatement;
const Program = T.Program;
const Statement = T.Statement;
const FunctionDeclaration = T.FunctionDeclaration;
const FunctionExpression = T.FunctionExpression;
const ConditionalExpression = T.ConditionalExpression;
const ObjectExpression = T.ObjectExpression;
const ArrayExpression = T.ArrayExpression;
const UnaryExpression = T.UnaryExpression;
const NewExpression = T.NewExpression;
const UpdateExpression = T.UpdateExpression;
const ForStatement = T.ForStatement;
const BlockStatement = T.BlockStatement;
const ThisExpression = T.ThisExpression;
const TypeAliasDirective = T.TypeAliasDirective;
const CastExpression = T.CastExpression;
const ThrowStatement = T.ThrowStatement;
const IfStatement = T.IfStatement;
const WhileStatement = T.WhileStatement;
const BreakStatement = T.BreakStatement;
const ContinueStatement = T.ContinueStatement;
const SwitchStatement = T.SwitchStatement;
const SwitchCase = T.SwitchCase;
const TryStatement = T.TryStatement;
const CatchClause = T.CatchClause;
var Literal = T.Literal;
var Identifier = T.Identifier;
var VariableDeclaration = T.VariableDeclaration;
var VariableDeclarator = T.VariableDeclarator;
var MemberExpression = T.MemberExpression;
var BinaryExpression = T.BinaryExpression;
var SequenceExpression = T.SequenceExpression;
var CallExpression = T.CallExpression;
var AssignmentExpression = T.AssignmentExpression;
var ExpressionStatement = T.ExpressionStatement;
var ReturnStatement = T.ReturnStatement;
var Program = T.Program;
var Statement = T.Statement;
var FunctionDeclaration = T.FunctionDeclaration;
var FunctionExpression = T.FunctionExpression;
var ConditionalExpression = T.ConditionalExpression;
var ObjectExpression = T.ObjectExpression;
var ArrayExpression = T.ArrayExpression;
var UnaryExpression = T.UnaryExpression;
var NewExpression = T.NewExpression;
var UpdateExpression = T.UpdateExpression;
var ForStatement = T.ForStatement;
var BlockStatement = T.BlockStatement;
var ThisExpression = T.ThisExpression;
var TypeAliasDirective = T.TypeAliasDirective;
var CastExpression = T.CastExpression;
var ThrowStatement = T.ThrowStatement;
var IfStatement = T.IfStatement;
var WhileStatement = T.WhileStatement;
var BreakStatement = T.BreakStatement;
var ContinueStatement = T.ContinueStatement;
var SwitchStatement = T.SwitchStatement;
var SwitchCase = T.SwitchCase;
var TryStatement = T.TryStatement;
var CatchClause = T.CatchClause;
/**
* When adding a new "magic" variable that the compiler has
@ -88,25 +88,25 @@ const CatchClause = T.CatchClause;
* where the "%d" is the stack index that the value occupies.
*/
const VAR_PREFIX = "v";
const LOCAL_PREFIX = "l";
const STACK_PREFIX = "s";
const ARGUMENT_PREFIX = "a";
const INLINE_CACHE_GETTER_PREFIX = "get";
const INLINE_CACHE_SETTER_PREFIX = "set";
var VAR_PREFIX = "v";
var LOCAL_PREFIX = "l";
var STACK_PREFIX = "s";
var ARGUMENT_PREFIX = "a";
var INLINE_CACHE_GETTER_PREFIX = "get";
var INLINE_CACHE_SETTER_PREFIX = "set";
const SAVED_SCOPE_NAME = "$SS";
const scopeName = new Identifier("$S");
const scopeObjectName = new Identifier("$O");
const globalScopeObjectName = new Identifier("$G");
const savedScopeName = new Identifier(SAVED_SCOPE_NAME);
const constantsName = new Identifier("$C");
const lastCaughtName = new Identifier("$E");
const exceptionName = new Identifier("$e");
const labelTestName = new Identifier("$label");
const labelConditionName = new Identifier("$condition");
const labelDeterminantName = new Identifier("$determinant");
const activationName = new Identifier("$activation");
var SAVED_SCOPE_NAME = "$SS";
var scopeName = new Identifier("$S");
var scopeObjectName = new Identifier("$O");
var globalScopeObjectName = new Identifier("$G");
var savedScopeName = new Identifier(SAVED_SCOPE_NAME);
var constantsName = new Identifier("$C");
var lastCaughtName = new Identifier("$E");
var exceptionName = new Identifier("$e");
var labelTestName = new Identifier("$label");
var labelConditionName = new Identifier("$condition");
var labelDeterminantName = new Identifier("$determinant");
var activationName = new Identifier("$activation");
/**
* To embed object references in compiled code we index into globally accessible constant table [$C].
@ -125,7 +125,7 @@ function notUndefined(x) {
return x !== undefined;
}
const FlushStackReason = {
var FlushStackReason = {
EndOfBlock: 1,
SetLocal: 2
};
@ -891,15 +891,15 @@ var Compiler = (function () {
var temporary = this.temporary;
var cachedScopes = this.cachedScopes;
const abc = this.compiler.abc;
const ints = abc.constantPool.ints;
const uints = abc.constantPool.uints;
const doubles = abc.constantPool.doubles;
const strings = abc.constantPool.strings;
const methods = abc.methods;
const multinames = abc.constantPool.multinames;
const runtime = abc.runtime;
const exceptions = this.methodInfo.exceptions;
var abc = this.compiler.abc;
var ints = abc.constantPool.ints;
var uints = abc.constantPool.uints;
var doubles = abc.constantPool.doubles;
var strings = abc.constantPool.strings;
var methods = abc.methods;
var multinames = abc.constantPool.multinames;
var runtime = abc.runtime;
var exceptions = this.methodInfo.exceptions;
var savedScope = this.savedScope;
var multiname, args, value, obj, qn, ns, name, type, factory, index;
@ -911,7 +911,7 @@ var Compiler = (function () {
}
function superClassInstanceObject() {
return property(classObject(), "baseClass", "instance");
return property(classObject(), "baseClass", "instanceNoInitialize");
}
function superOf(obj) {

Просмотреть файл

@ -1,248 +1,248 @@
const CONSTANT_Undefined = 0x00;
const CONSTANT_Utf8 = 0x01;
const CONSTANT_Float = 0x02; // May be deprecated ??
const CONSTANT_Int = 0x03;
const CONSTANT_UInt = 0x04;
const CONSTANT_PrivateNs = 0x05;
const CONSTANT_Double = 0x06;
const CONSTANT_QName = 0x07; // ns::name, const ns, const name
const CONSTANT_Namespace = 0x08;
const CONSTANT_Multiname = 0x09; // [ns...]::name, const [ns...], const name
const CONSTANT_False = 0x0A;
const CONSTANT_True = 0x0B;
const CONSTANT_Null = 0x0C;
const CONSTANT_QNameA = 0x0D; // @ns::name, const ns, const name
const CONSTANT_MultinameA = 0x0E; // @[ns...]::name, const [ns...], const name
const CONSTANT_RTQName = 0x0F; // ns::name, var ns, const name
const CONSTANT_RTQNameA = 0x10; // @ns::name, var ns, const name
const CONSTANT_RTQNameL = 0x11; // ns::[name], var ns, var name
const CONSTANT_RTQNameLA = 0x12; // @ns::[name], var ns, var name
const CONSTANT_NameL = 0x13; // o[name], var name
const CONSTANT_NameLA = 0x14; // @[name], var name
const CONSTANT_NamespaceSet = 0x15;
const CONSTANT_PackageNamespace = 0x16; // namespace for a package
const CONSTANT_PackageInternalNs = 0x17;
const CONSTANT_ProtectedNamespace = 0x18;
const CONSTANT_ExplicitNamespace = 0x19;
const CONSTANT_StaticProtectedNs = 0x1A;
const CONSTANT_MultinameL = 0x1B;
const CONSTANT_MultinameLA = 0x1C;
const CONSTANT_TypeName = 0x1D;
var CONSTANT_Undefined = 0x00;
var CONSTANT_Utf8 = 0x01;
var CONSTANT_Float = 0x02; // May be deprecated ??
var CONSTANT_Int = 0x03;
var CONSTANT_UInt = 0x04;
var CONSTANT_PrivateNs = 0x05;
var CONSTANT_Double = 0x06;
var CONSTANT_QName = 0x07; // ns::name, const ns, const name
var CONSTANT_Namespace = 0x08;
var CONSTANT_Multiname = 0x09; // [ns...]::name, const [ns...], const name
var CONSTANT_False = 0x0A;
var CONSTANT_True = 0x0B;
var CONSTANT_Null = 0x0C;
var CONSTANT_QNameA = 0x0D; // @ns::name, const ns, const name
var CONSTANT_MultinameA = 0x0E; // @[ns...]::name, const [ns...], const name
var CONSTANT_RTQName = 0x0F; // ns::name, var ns, const name
var CONSTANT_RTQNameA = 0x10; // @ns::name, var ns, const name
var CONSTANT_RTQNameL = 0x11; // ns::[name], var ns, var name
var CONSTANT_RTQNameLA = 0x12; // @ns::[name], var ns, var name
var CONSTANT_NameL = 0x13; // o[name], var name
var CONSTANT_NameLA = 0x14; // @[name], var name
var CONSTANT_NamespaceSet = 0x15;
var CONSTANT_PackageNamespace = 0x16; // namespace for a package
var CONSTANT_PackageInternalNs = 0x17;
var CONSTANT_ProtectedNamespace = 0x18;
var CONSTANT_ExplicitNamespace = 0x19;
var CONSTANT_StaticProtectedNs = 0x1A;
var CONSTANT_MultinameL = 0x1B;
var CONSTANT_MultinameLA = 0x1C;
var CONSTANT_TypeName = 0x1D;
const CONSTANT_ClassSealed = 0x01;
const CONSTANT_ClassFinal = 0x02;
const CONSTANT_ClassInterface = 0x04;
const CONSTANT_ClassProtectedNs = 0x08;
var CONSTANT_ClassSealed = 0x01;
var CONSTANT_ClassFinal = 0x02;
var CONSTANT_ClassInterface = 0x04;
var CONSTANT_ClassProtectedNs = 0x08;
const TRAIT_Slot = 0;
const TRAIT_Method = 1;
const TRAIT_Getter = 2;
const TRAIT_Setter = 3;
const TRAIT_Class = 4;
const TRAIT_Function = 5;
const TRAIT_Const = 6;
var TRAIT_Slot = 0;
var TRAIT_Method = 1;
var TRAIT_Getter = 2;
var TRAIT_Setter = 3;
var TRAIT_Class = 4;
var TRAIT_Function = 5;
var TRAIT_Const = 6;
const ATTR_Final = 0x01;
const ATTR_Override = 0x02;
const ATTR_Metadata = 0x04;
var ATTR_Final = 0x01;
var ATTR_Override = 0x02;
var ATTR_Metadata = 0x04;
const SLOT_var = 0;
const SLOT_method = 1;
const SLOT_getter = 2;
const SLOT_setter = 3;
const SLOT_class = 4;
const SLOT_function = 6;
var SLOT_var = 0;
var SLOT_method = 1;
var SLOT_getter = 2;
var SLOT_setter = 3;
var SLOT_class = 4;
var SLOT_function = 6;
const METHOD_Arguments = 0x1;
const METHOD_Activation = 0x2;
const METHOD_Needrest = 0x4;
const METHOD_HasOptional = 0x8;
const METHOD_IgnoreRest = 0x10;
const METHOD_Native = 0x20;
const METHOD_Setsdxns = 0x40;
const METHOD_HasParamNames = 0x80;
var METHOD_Arguments = 0x1;
var METHOD_Activation = 0x2;
var METHOD_Needrest = 0x4;
var METHOD_HasOptional = 0x8;
var METHOD_IgnoreRest = 0x10;
var METHOD_Native = 0x20;
var METHOD_Setsdxns = 0x40;
var METHOD_HasParamNames = 0x80;
const OP_bkpt = 0x01;
const OP_nop = 0x02;
const OP_throw = 0x03;
const OP_getsuper = 0x04;
const OP_setsuper = 0x05;
const OP_dxns = 0x06;
const OP_dxnslate = 0x07;
const OP_kill = 0x08;
const OP_label = 0x09;
const OP_lf32x4 = 0x0A;
const OP_sf32x4 = 0x0B;
const OP_ifnlt = 0x0C;
const OP_ifnle = 0x0D;
const OP_ifngt = 0x0E;
const OP_ifnge = 0x0F;
const OP_jump = 0x10;
const OP_iftrue = 0x11;
const OP_iffalse = 0x12;
const OP_ifeq = 0x13;
const OP_ifne = 0x14;
const OP_iflt = 0x15;
const OP_ifle = 0x16;
const OP_ifgt = 0x17;
const OP_ifge = 0x18;
const OP_ifstricteq = 0x19;
const OP_ifstrictne = 0x1A;
const OP_lookupswitch = 0x1B;
const OP_pushwith = 0x1C;
const OP_popscope = 0x1D;
const OP_nextname = 0x1E;
const OP_hasnext = 0x1F;
const OP_pushnull = 0x20;
const OP_pushundefined = 0x21;
const OP_pushfloat = 0x22;
const OP_nextvalue = 0x23;
const OP_pushbyte = 0x24;
const OP_pushshort = 0x25;
const OP_pushtrue = 0x26;
const OP_pushfalse = 0x27;
const OP_pushnan = 0x28;
const OP_pop = 0x29;
const OP_dup = 0x2A;
const OP_swap = 0x2B;
const OP_pushstring = 0x2C;
const OP_pushint = 0x2D;
const OP_pushuint = 0x2E;
const OP_pushdouble = 0x2F;
const OP_pushscope = 0x30;
const OP_pushnamespace = 0x31;
const OP_hasnext2 = 0x32;
const OP_li8 = 0x35;
const OP_li16 = 0x36;
const OP_li32 = 0x37;
const OP_lf32 = 0x38;
const OP_lf64 = 0x39;
const OP_si8 = 0x3A;
const OP_si16 = 0x3B;
const OP_si32 = 0x3C;
const OP_sf32 = 0x3D;
const OP_sf64 = 0x3E;
const OP_newfunction = 0x40;
const OP_call = 0x41;
const OP_construct = 0x42;
const OP_callmethod = 0x43;
const OP_callstatic = 0x44;
const OP_callsuper = 0x45;
const OP_callproperty = 0x46;
const OP_returnvoid = 0x47;
const OP_returnvalue = 0x48;
const OP_constructsuper = 0x49;
const OP_constructprop = 0x4A;
const OP_callsuperid = 0x4B;
const OP_callproplex = 0x4C;
const OP_callinterface = 0x4D;
const OP_callsupervoid = 0x4E;
const OP_callpropvoid = 0x4F;
const OP_sxi1 = 0x50;
const OP_sxi8 = 0x51;
const OP_sxi16 = 0x52;
const OP_applytype = 0x53;
const OP_pushfloat4 = 0x54;
const OP_newobject = 0x55;
const OP_newarray = 0x56;
const OP_newactivation = 0x57;
const OP_newclass = 0x58;
const OP_getdescendants = 0x59;
const OP_newcatch = 0x5A;
const OP_findpropstrict = 0x5D;
const OP_findproperty = 0x5E;
const OP_finddef = 0x5F;
const OP_getlex = 0x60;
const OP_setproperty = 0x61;
const OP_getlocal = 0x62;
const OP_setlocal = 0x63;
const OP_getglobalscope = 0x64;
const OP_getscopeobject = 0x65;
const OP_getproperty = 0x66;
const OP_getouterscope = 0x67;
const OP_initproperty = 0x68;
const OP_setpropertylate = 0x69;
const OP_deleteproperty = 0x6A;
const OP_deletepropertylate = 0x6B;
const OP_getslot = 0x6C;
const OP_setslot = 0x6D;
const OP_getglobalslot = 0x6E;
const OP_setglobalslot = 0x6F;
const OP_convert_s = 0x70;
const OP_esc_xelem = 0x71;
const OP_esc_xattr = 0x72;
const OP_convert_i = 0x73;
const OP_convert_u = 0x74;
const OP_convert_d = 0x75;
const OP_convert_b = 0x76;
const OP_convert_o = 0x77;
const OP_checkfilter = 0x78;
const OP_convert_f = 0x79;
const OP_unplus = 0x7a;
const OP_convert_f4 = 0x7b;
const OP_coerce = 0x80;
const OP_coerce_b = 0x81;
const OP_coerce_a = 0x82;
const OP_coerce_i = 0x83;
const OP_coerce_d = 0x84;
const OP_coerce_s = 0x85;
const OP_astype = 0x86;
const OP_astypelate = 0x87;
const OP_coerce_u = 0x88;
const OP_coerce_o = 0x89;
const OP_negate = 0x90;
const OP_increment = 0x91;
const OP_inclocal = 0x92;
const OP_decrement = 0x93;
const OP_declocal = 0x94;
const OP_typeof = 0x95;
const OP_not = 0x96;
const OP_bitnot = 0x97;
const OP_add = 0xA0;
const OP_subtract = 0xA1;
const OP_multiply = 0xA2;
const OP_divide = 0xA3;
const OP_modulo = 0xA4;
const OP_lshift = 0xA5;
const OP_rshift = 0xA6;
const OP_urshift = 0xA7;
const OP_bitand = 0xA8;
const OP_bitor = 0xA9;
const OP_bitxor = 0xAA;
const OP_equals = 0xAB;
const OP_strictequals = 0xAC;
const OP_lessthan = 0xAD;
const OP_lessequals = 0xAE;
const OP_greaterthan = 0xAF;
const OP_greaterequals = 0xB0;
const OP_instanceof = 0xB1;
const OP_istype = 0xB2;
const OP_istypelate = 0xB3;
const OP_in = 0xB4;
const OP_increment_i = 0xC0;
const OP_decrement_i = 0xC1;
const OP_inclocal_i = 0xC2;
const OP_declocal_i = 0xC3;
const OP_negate_i = 0xC4;
const OP_add_i = 0xC5;
const OP_subtract_i = 0xC6;
const OP_multiply_i = 0xC7;
const OP_getlocal0 = 0xD0;
const OP_getlocal1 = 0xD1;
const OP_getlocal2 = 0xD2;
const OP_getlocal3 = 0xD3;
const OP_setlocal0 = 0xD4;
const OP_setlocal1 = 0xD5;
const OP_setlocal2 = 0xD6;
const OP_setlocal3 = 0xD7;
const OP_invalid = 0xED;
const OP_debug = 0xEF;
const OP_debugline = 0xF0;
const OP_debugfile = 0xF1;
const OP_bkptline = 0xF2;
const OP_timestamp = 0xF3;
var OP_bkpt = 0x01;
var OP_nop = 0x02;
var OP_throw = 0x03;
var OP_getsuper = 0x04;
var OP_setsuper = 0x05;
var OP_dxns = 0x06;
var OP_dxnslate = 0x07;
var OP_kill = 0x08;
var OP_label = 0x09;
var OP_lf32x4 = 0x0A;
var OP_sf32x4 = 0x0B;
var OP_ifnlt = 0x0C;
var OP_ifnle = 0x0D;
var OP_ifngt = 0x0E;
var OP_ifnge = 0x0F;
var OP_jump = 0x10;
var OP_iftrue = 0x11;
var OP_iffalse = 0x12;
var OP_ifeq = 0x13;
var OP_ifne = 0x14;
var OP_iflt = 0x15;
var OP_ifle = 0x16;
var OP_ifgt = 0x17;
var OP_ifge = 0x18;
var OP_ifstricteq = 0x19;
var OP_ifstrictne = 0x1A;
var OP_lookupswitch = 0x1B;
var OP_pushwith = 0x1C;
var OP_popscope = 0x1D;
var OP_nextname = 0x1E;
var OP_hasnext = 0x1F;
var OP_pushnull = 0x20;
var OP_pushundefined = 0x21;
var OP_pushfloat = 0x22;
var OP_nextvalue = 0x23;
var OP_pushbyte = 0x24;
var OP_pushshort = 0x25;
var OP_pushtrue = 0x26;
var OP_pushfalse = 0x27;
var OP_pushnan = 0x28;
var OP_pop = 0x29;
var OP_dup = 0x2A;
var OP_swap = 0x2B;
var OP_pushstring = 0x2C;
var OP_pushint = 0x2D;
var OP_pushuint = 0x2E;
var OP_pushdouble = 0x2F;
var OP_pushscope = 0x30;
var OP_pushnamespace = 0x31;
var OP_hasnext2 = 0x32;
var OP_li8 = 0x35;
var OP_li16 = 0x36;
var OP_li32 = 0x37;
var OP_lf32 = 0x38;
var OP_lf64 = 0x39;
var OP_si8 = 0x3A;
var OP_si16 = 0x3B;
var OP_si32 = 0x3C;
var OP_sf32 = 0x3D;
var OP_sf64 = 0x3E;
var OP_newfunction = 0x40;
var OP_call = 0x41;
var OP_construct = 0x42;
var OP_callmethod = 0x43;
var OP_callstatic = 0x44;
var OP_callsuper = 0x45;
var OP_callproperty = 0x46;
var OP_returnvoid = 0x47;
var OP_returnvalue = 0x48;
var OP_constructsuper = 0x49;
var OP_constructprop = 0x4A;
var OP_callsuperid = 0x4B;
var OP_callproplex = 0x4C;
var OP_callinterface = 0x4D;
var OP_callsupervoid = 0x4E;
var OP_callpropvoid = 0x4F;
var OP_sxi1 = 0x50;
var OP_sxi8 = 0x51;
var OP_sxi16 = 0x52;
var OP_applytype = 0x53;
var OP_pushfloat4 = 0x54;
var OP_newobject = 0x55;
var OP_newarray = 0x56;
var OP_newactivation = 0x57;
var OP_newclass = 0x58;
var OP_getdescendants = 0x59;
var OP_newcatch = 0x5A;
var OP_findpropstrict = 0x5D;
var OP_findproperty = 0x5E;
var OP_finddef = 0x5F;
var OP_getlex = 0x60;
var OP_setproperty = 0x61;
var OP_getlocal = 0x62;
var OP_setlocal = 0x63;
var OP_getglobalscope = 0x64;
var OP_getscopeobject = 0x65;
var OP_getproperty = 0x66;
var OP_getouterscope = 0x67;
var OP_initproperty = 0x68;
var OP_setpropertylate = 0x69;
var OP_deleteproperty = 0x6A;
var OP_deletepropertylate = 0x6B;
var OP_getslot = 0x6C;
var OP_setslot = 0x6D;
var OP_getglobalslot = 0x6E;
var OP_setglobalslot = 0x6F;
var OP_convert_s = 0x70;
var OP_esc_xelem = 0x71;
var OP_esc_xattr = 0x72;
var OP_convert_i = 0x73;
var OP_convert_u = 0x74;
var OP_convert_d = 0x75;
var OP_convert_b = 0x76;
var OP_convert_o = 0x77;
var OP_checkfilter = 0x78;
var OP_convert_f = 0x79;
var OP_unplus = 0x7a;
var OP_convert_f4 = 0x7b;
var OP_coerce = 0x80;
var OP_coerce_b = 0x81;
var OP_coerce_a = 0x82;
var OP_coerce_i = 0x83;
var OP_coerce_d = 0x84;
var OP_coerce_s = 0x85;
var OP_astype = 0x86;
var OP_astypelate = 0x87;
var OP_coerce_u = 0x88;
var OP_coerce_o = 0x89;
var OP_negate = 0x90;
var OP_increment = 0x91;
var OP_inclocal = 0x92;
var OP_decrement = 0x93;
var OP_declocal = 0x94;
var OP_typeof = 0x95;
var OP_not = 0x96;
var OP_bitnot = 0x97;
var OP_add = 0xA0;
var OP_subtract = 0xA1;
var OP_multiply = 0xA2;
var OP_divide = 0xA3;
var OP_modulo = 0xA4;
var OP_lshift = 0xA5;
var OP_rshift = 0xA6;
var OP_urshift = 0xA7;
var OP_bitand = 0xA8;
var OP_bitor = 0xA9;
var OP_bitxor = 0xAA;
var OP_equals = 0xAB;
var OP_strictequals = 0xAC;
var OP_lessthan = 0xAD;
var OP_lessequals = 0xAE;
var OP_greaterthan = 0xAF;
var OP_greaterequals = 0xB0;
var OP_instanceof = 0xB1;
var OP_istype = 0xB2;
var OP_istypelate = 0xB3;
var OP_in = 0xB4;
var OP_increment_i = 0xC0;
var OP_decrement_i = 0xC1;
var OP_inclocal_i = 0xC2;
var OP_declocal_i = 0xC3;
var OP_negate_i = 0xC4;
var OP_add_i = 0xC5;
var OP_subtract_i = 0xC6;
var OP_multiply_i = 0xC7;
var OP_getlocal0 = 0xD0;
var OP_getlocal1 = 0xD1;
var OP_getlocal2 = 0xD2;
var OP_getlocal3 = 0xD3;
var OP_setlocal0 = 0xD4;
var OP_setlocal1 = 0xD5;
var OP_setlocal2 = 0xD6;
var OP_setlocal3 = 0xD7;
var OP_invalid = 0xED;
var OP_debug = 0xEF;
var OP_debugline = 0xF0;
var OP_debugfile = 0xF1;
var OP_bkptline = 0xF2;
var OP_timestamp = 0xF3;
const INT_MIN_VALUE = -0x80000000;
const INT_MAX_VALUE = 0x7fffffff;
const UINT_MIN_VALUE = 0;
const UINT_MAX_VALUE = 0xffffffff;
var INT_MIN_VALUE = -0x80000000;
var INT_MAX_VALUE = 0x7fffffff;
var UINT_MIN_VALUE = 0;
var UINT_MAX_VALUE = 0xffffffff;

Просмотреть файл

@ -242,8 +242,8 @@ var SourceTracer = (function () {
SourceTracer.prototype = {
traceTraits: function traceTraits(traits, isStatic, inInterfaceNamespace) {
const writer = this.writer;
const tracer = this;
var writer = this.writer;
var tracer = this;
traits.forEach(function (trait) {
var str;
@ -316,7 +316,7 @@ var SourceTracer = (function () {
},
traceClassStub2: function traceClassStub(trait) {
const writer = this.writer;
var writer = this.writer;
var ci = trait.classInfo;
var ii = ci.instanceInfo;
@ -379,7 +379,7 @@ var SourceTracer = (function () {
},
traceClassStub: function traceClassStub(trait) {
const writer = this.writer;
var writer = this.writer;
var ci = trait.classInfo;
var ii = ci.instanceInfo;
@ -486,7 +486,7 @@ var SourceTracer = (function () {
},
traceClass: function traceClass(ci) {
const writer = this.writer;
var writer = this.writer;
var ii = ci.instanceInfo;
var name = ii.name;
@ -521,7 +521,7 @@ var SourceTracer = (function () {
},
traceMetadata: function traceMetadata(metadata) {
const writer = this.writer;
var writer = this.writer;
for (var key in metadata) {
if (metadata.hasOwnProperty(key)) {

Просмотреть файл

@ -2,7 +2,7 @@ var domainOptions = systemOptions.register(new OptionSet("Domain Options"));
var traceClasses = domainOptions.register(new Option("tc", "traceClasses", "boolean", false, "trace class creation"));
var traceDomain = domainOptions.register(new Option("tdpa", "traceDomain", "boolean", false, "trace domain property access"));
const EXECUTION_MODE = {
var EXECUTION_MODE = {
INTERPRET: 0x1,
COMPILE: 0x2
};
@ -44,12 +44,17 @@ var Domain = (function () {
} else {
this.system = this;
var OWN_INITIALIZE = 0x1;
var SUPER_INITIALIZE = 0x2;
var Class = this.Class = function Class(name, instance, callable) {
this.debugName = name;
if (instance) {
release || assert(instance.prototype);
this.instance = instance;
this.instanceNoInitialize = instance;
this.hasInitialize = 0;
}
if (!callable) {
@ -77,12 +82,12 @@ var Domain = (function () {
var c = this;
var initializes = [];
while (c) {
var s = c.instance.prototype.initialize;
if (s) {
initializes.push(s);
if (c.hasInitialize & OWN_INITIALIZE) {
initializes.push(c.instance.prototype.initialize);
}
c = c.baseClass;
}
var s;
while (s = initializes.pop()) {
s.call(obj);
}
@ -129,6 +134,15 @@ var Domain = (function () {
extend: function (baseClass) {
this.baseClass = baseClass;
this.dynamicPrototype = Object.create(baseClass.dynamicPrototype);
if (baseClass.hasInitialize) {
var instanceNoInitialize = this.instance;
var self = this;
this.instance = function () {
self.initializeInstance(this);
instanceNoInitialize.apply(this, arguments);
};
this.hasInitialize |= SUPER_INITIALIZE;
}
this.instance.prototype = Object.create(this.dynamicPrototype);
defineNonEnumerableProperty(this.dynamicPrototype, "public$constructor", this);
defineReadOnlyProperty(this.instance.prototype, "class", this);
@ -155,6 +169,19 @@ var Domain = (function () {
}
}
if (definition.initialize) {
if (!this.hasInitialize) {
var instanceNoInitialize = this.instance;
var self = this;
this.instance = function () {
self.initializeInstance(this);
instanceNoInitialize.apply(this, arguments);
};
this.instance.prototype = instanceNoInitialize.prototype;
}
this.hasInitialize |= OWN_INITIALIZE;
}
var proto = this.dynamicPrototype;
var keys = Object.keys(definition);
for (var i = 0, j = keys.length; i < j; i++) {

Просмотреть файл

@ -1,4 +1,4 @@
const Errors = {
var Errors = {
OutOfMemoryError : {code: 1000, message: "The system is out of memory."},
NotImplementedError : {code: 1001, message: "The method %1 is not implemented."},
InvalidPrecisionError : {code: 1002, message: "Number.toPrecision has a range of 1 to 21. Number.toFixed and Number.toExponential have a range of 0 to 20. Specified value is not within expected range."},
@ -139,6 +139,7 @@ const Errors = {
NullPointerError : {code: 2007, message: "Parameter %1 must be non-null."},
InvalidEnumError : {code: 2008, message: "Parameter %1 must be one of the accepted values."},
CantInstantiateError : {code: 2012, message: "%1 class cannot be instantiated."},
ArgumentError : {code: 2015, message: "Invalid BitmapData."},
EOFError : {code: 2030, message: "End of file was encountered."},
CompressedDataError : {code: 2058, message: "There was an error decompressing the data."},
EmptyStringError : {code: 2085, message: "Parameter %1 must be non-empty string."},

Просмотреть файл

@ -11,7 +11,7 @@ var Interpreter = (function () {
this.abc = abc;
}
const Apslice = [].slice;
var Apslice = [].slice;
function applyNew(constructor, args) {
return new (Function.bind.apply(constructor.instance, [,].concat(args)));
@ -41,16 +41,16 @@ var Interpreter = (function () {
interpretMethod: function interpretMethod($this, method, savedScope, args) {
release || assert(method.analysis);
Counter.count("Interpret Method");
const abc = this.abc;
const ints = abc.constantPool.ints;
const uints = abc.constantPool.uints;
const doubles = abc.constantPool.doubles;
const strings = abc.constantPool.strings;
const methods = abc.methods;
const multinames = abc.constantPool.multinames;
const runtime = abc.runtime;
const domain = abc.domain;
const rtstack = Runtime.stack;
var abc = this.abc;
var ints = abc.constantPool.ints;
var uints = abc.constantPool.uints;
var doubles = abc.constantPool.doubles;
var strings = abc.constantPool.strings;
var methods = abc.methods;
var multinames = abc.constantPool.multinames;
var runtime = abc.runtime;
var domain = abc.domain;
var rtstack = Runtime.stack;
var exceptions = method.exceptions;
@ -322,7 +322,7 @@ var Interpreter = (function () {
case OP_constructsuper:
args = stack.popMany(bc.argCount);
obj = stack.pop();
savedScope.object.baseClass.instance.apply(obj, args);
savedScope.object.baseClass.instanceNoInitialize.apply(obj, args);
break;
case OP_constructprop:
args = stack.popMany(bc.argCount);

Просмотреть файл

@ -175,7 +175,7 @@
* instantiation. It is called in the usual order for its super classes,
* i.e. super first.
*
* Suppose c is an instance of C, is has access to the definitions:
* Suppose c is an instance of C, it has access to the definitions:
*
* c.m(); // calls m
* print(c.x); // calls the getter
@ -206,10 +206,10 @@ defineReadOnlyProperty(Object.prototype, "isInstance", function () {
});
*/
const natives = (function () {
var natives = (function () {
const C = Domain.passthroughCallable;
const CC = Domain.constructingCallable;
var C = Domain.passthroughCallable;
var CC = Domain.constructingCallable;
/**
* Object.as
@ -472,7 +472,7 @@ const natives = (function () {
* Vector.as
*/
const VM_VECTOR_IS_FIXED = "vm vector is fixed";
var VM_VECTOR_IS_FIXED = "vm vector is fixed";
/**
* Creates a typed Vector class. It steals the Array object from a new global
@ -485,7 +485,7 @@ const natives = (function () {
// Breaks semantics with bounds checking for now.
if (type) {
const coerce = type.coerce;
var coerce = type.coerce;
TAp.indexGet = function (i) { return this[i]; };
TAp.indexSet = function (i, v) { this[i] = coerce(v); };
}
@ -699,11 +699,7 @@ const natives = (function () {
};
return function (runtime, scope, instance, baseClass) {
var instance2 = function () {
this.class.initializeInstance(this);
instance.apply(this, arguments);
};
var c = new runtime.domain.system.Class(name, instance2, CC(instance2));
var c = new runtime.domain.system.Class(name, instance);
c.extend(baseClass);
if (name === "Error") {
c.link(ErrorDefinition);
@ -930,11 +926,10 @@ const natives = (function () {
*/
function ByteArrayClass(runtime, scope, instance, baseClass) {
/* The initial size of the backing, in bytes. Doubled every OOM. */
const INITIAL_SIZE = 128;
var INITIAL_SIZE = 128;
function ByteArray() {
var a = new ArrayBuffer(INITIAL_SIZE);
this.a = a;
this.a = new ArrayBuffer(INITIAL_SIZE);
this.length = 0;
this.position = 0;
this.cacheViews();
@ -1033,7 +1028,7 @@ const natives = (function () {
BAp.writeBoolean = function writeBoolean(v) {
var len = this.position + 1;
this.ensureCapacity(len);
this.int8v[this.position++] = !!v ? 1 : 0;
this.int8v[this.position++] = v ? 1 : 0;
if (len > this.length) {
this.length = len;
}

Просмотреть файл

@ -136,10 +136,10 @@ function parseTraits(abc, stream, holder) {
var Trait = (function () {
function trait(abc, stream, holder) {
const constantPool = abc.constantPool;
const methods = abc.methods;
const classes = abc.classes;
const metadata = abc.metadata;
var constantPool = abc.constantPool;
var methods = abc.methods;
var classes = abc.classes;
var metadata = abc.metadata;
this.holder = holder;
this.name = constantPool.multinames[stream.readU30()];
@ -254,8 +254,8 @@ var Namespace = (function () {
* According to Tamarin, this is 0xe000 + 660, with 660 being an "odd legacy
* wart".
*/
const MIN_API_MARK = 0xe294;
const MAX_API_MARK = 0xf8ff;
var MIN_API_MARK = 0xe294;
var MAX_API_MARK = 0xf8ff;
function namespace(kind, uri) {
if (kind !== undefined) {
@ -435,9 +435,9 @@ var Namespace = (function () {
*/
var Multiname = (function () {
const ATTRIBUTE = 0x01;
const RUNTIME_NAMESPACE = 0x02;
const RUNTIME_NAME = 0x04;
var ATTRIBUTE = 0x01;
var RUNTIME_NAMESPACE = 0x02;
var RUNTIME_NAME = 0x04;
var nextID = 1;
function multiname(namespaces, name, flags) {
this.id = nextID ++;
@ -871,7 +871,7 @@ var MethodInfo = (function () {
}
function methodInfo(abc, stream) {
const constantPool = abc.constantPool;
var constantPool = abc.constantPool;
var parameterCount = stream.readU30();
var returnType = constantPool.multinames[stream.readU30()];
@ -932,7 +932,7 @@ var MethodInfo = (function () {
};
function parseException(abc, stream) {
const multinames = abc.constantPool.multinames;
var multinames = abc.constantPool.multinames;
var ex = {
start: stream.readU30(),
@ -947,8 +947,8 @@ var MethodInfo = (function () {
}
methodInfo.parseBody = function parseBody(abc, stream) {
const constantPool = abc.constantPool;
const methods = abc.methods;
var constantPool = abc.constantPool;
var methods = abc.methods;
var info = methods[stream.readU30()];
release || assert(!info.isNative());
@ -976,7 +976,7 @@ var MethodInfo = (function () {
var MetaDataInfo = (function () {
function metaDataInfo(abc, stream) {
const strings = abc.constantPool.strings;
var strings = abc.constantPool.strings;
this.tagName = strings[stream.readU30()];
var itemCount = stream.readU30();
@ -1021,8 +1021,8 @@ var InstanceInfo = (function () {
var nextID = 1;
function instanceInfo(abc, stream) {
this.id = nextID ++;
const constantPool = abc.constantPool;
const methods = abc.methods;
var constantPool = abc.constantPool;
var methods = abc.methods;
this.name = constantPool.multinames[stream.readU30()];
release || assert(Multiname.isQName(this.name));

Просмотреть файл

@ -8,31 +8,31 @@ var compileOnly = compilerOptions.register(new Option("co", "compileOnly", "numb
var compileUntil = compilerOptions.register(new Option("cu", "compileUntil", "number", -1, "Compiles only until a function number."));
var debuggerMode = runtimeOptions.register(new Option("dm", "debuggerMode", "boolean", false, "matches avm2 debugger build semantics"));
const jsGlobal = (function() { return this || (1, eval)('this'); })();
var jsGlobal = (function() { return this || (1, eval)('this'); })();
const VM_SLOTS = "vm slots";
const VM_LENGTH = "vm length";
const VM_BINDINGS = "vm bindings";
const VM_NATIVE_PROTOTYPE_FLAG = "vm native prototype";
const VM_ENUMERATION_KEYS = "vm enumeration keys";
const VM_OPEN_METHODS = "vm open methods";
const VM_NEXT_NAME = "vm next name";
const VM_NEXT_NAME_INDEX = "vm next name index";
const VM_UNSAFE_CLASSES = ["Shumway"];
var VM_SLOTS = "vm slots";
var VM_LENGTH = "vm length";
var VM_BINDINGS = "vm bindings";
var VM_NATIVE_PROTOTYPE_FLAG = "vm native prototype";
var VM_ENUMERATION_KEYS = "vm enumeration keys";
var VM_OPEN_METHODS = "vm open methods";
var VM_NEXT_NAME = "vm next name";
var VM_NEXT_NAME_INDEX = "vm next name index";
var VM_UNSAFE_CLASSES = ["Shumway"];
const VM_NATIVE_BUILTINS = [Object, Number, Boolean, String, Array, Date, RegExp];
var VM_NATIVE_BUILTINS = [Object, Number, Boolean, String, Array, Date, RegExp];
var VM_NATIVE_BUILTIN_SURROGATES = [
{ object: Object, methods: ["toString", "valueOf"] },
{ object: Function, methods: ["toString", "valueOf"] }
];
const VM_NATIVE_BUILTIN_ORIGINALS = "vm originals";
var VM_NATIVE_BUILTIN_ORIGINALS = "vm originals";
var $M = [];
function initializeGlobalObject(global) {
const PUBLIC_MANGLED = /^public\$/;
var PUBLIC_MANGLED = /^public\$/;
function getEnumerationKeys(obj) {
var keys = [];
@ -161,7 +161,7 @@ function coerce(value, type) {
return type.coerce(value);
}
if (isNullOrUndefiend(value)) {
if (isNullOrUndefined(value)) {
return null;
}
@ -787,11 +787,11 @@ var Runtime = (function () {
* compiler bakes it in as a constant which should be much more efficient.
*/
runtime.prototype.createFunction = function createFunction(methodInfo, scope, hasDynamicScope) {
const mi = methodInfo;
var mi = methodInfo;
release || assert(!mi.isNative(), "Method should have a builtin: ", mi.name);
var hasDefaults = false;
const defaults = mi.parameters.map(function (p) {
var defaults = mi.parameters.map(function (p) {
if (p.value !== undefined) {
hasDefaults = true;
}
@ -814,7 +814,7 @@ var Runtime = (function () {
return fn;
}
const mode = this.domain.mode;
var mode = this.domain.mode;
// We use not having an analysis to mean "not initialized".
if (!mi.analysis) {
@ -955,7 +955,7 @@ var Runtime = (function () {
return this.createInterface(classInfo);
}
const domain = this.domain;
var domain = this.domain;
var className = Multiname.getName(ii.name);
if (traceExecution.value) {
@ -1011,7 +1011,7 @@ var Runtime = (function () {
cls.scope = scope;
scope.object = cls;
cls.extend(baseClass);
this.applyTraits(instance.prototype, scope, baseBindings, ii.traits, null, true);
this.applyTraits(cls.instance.prototype, scope, baseBindings, ii.traits, null, true);
this.applyTraits(cls, scope, null, ci.traits, null, false);
}
@ -1136,8 +1136,8 @@ var Runtime = (function () {
};
runtime.prototype.applyTraits = function applyTraits(obj, scope, base, traits, classNatives, delayBinding) {
const runtime = this;
const domain = this.domain;
var runtime = this;
var domain = this.domain;
function makeClosure(trait) {
release || assert(scope);
@ -1246,7 +1246,7 @@ var Runtime = (function () {
} else if (trait.isMethod()) {
// FIXME: Breaking compat with AS and using .bind here instead of the
// MethodClosure class to work around a SpiderMonkey bug 771871.
const MethodClosureClass = domain.system.MethodClosureClass;
var MethodClosureClass = domain.system.MethodClosureClass;
var closure;

1
src/avm2/tests/.gitignore поставляемый
Просмотреть файл

@ -1,4 +1,5 @@
abc/
tamarin/
acceptance/
regress/*/*.abc
hello-world.abc

Просмотреть файл

@ -82,7 +82,7 @@ function defineNonEnumerableProperty(obj, name, value) {
enumerable: false });
}
function isNullOrUndefiend(value) {
function isNullOrUndefined(value) {
return value === null || value === undefined;
}
@ -269,7 +269,7 @@ function utf8decode(str) {
function utf8encode(bytes) {
var str = "";
const fcc = String.fromCharCode;
var fcc = String.fromCharCode;
for (var i = 0, j = bytes.length; i < j; i++) {
var b = bytes[i];
str += b <= 0x7f ? b === 0x25 ? "%25" : fcc(b) : "%" + b.toString(16).toUpperCase();
@ -304,10 +304,10 @@ function bitCount(i) {
* If the set fits in a single word, a single int is used.
*/
function BitSetFunctor(length) {
const ADDRESS_BITS_PER_WORD = 5;
const BITS_PER_WORD = 1 << ADDRESS_BITS_PER_WORD;
const BIT_INDEX_MASK = BITS_PER_WORD - 1;
const SIZE = ((length + (BITS_PER_WORD - 1)) >> ADDRESS_BITS_PER_WORD) << ADDRESS_BITS_PER_WORD;
var ADDRESS_BITS_PER_WORD = 5;
var BITS_PER_WORD = 1 << ADDRESS_BITS_PER_WORD;
var BIT_INDEX_MASK = BITS_PER_WORD - 1;
var SIZE = ((length + (BITS_PER_WORD - 1)) >> ADDRESS_BITS_PER_WORD) << ADDRESS_BITS_PER_WORD;
function BitSet() {
/* How many bits are set. */

Просмотреть файл

@ -0,0 +1,22 @@
var BitmapDefinition = (function () {
var def = {
__class__: 'flash.display.Bitmap',
draw : function(ctx, ratio) {
ctx.drawImage(this._bitmapData._canvas, 0, 0);
}
};
def.__glue__ = {
native: {
instance: {
ctor : function(bitmapData, pixelSnapping, smoothing) {
this._bitmapData = bitmapData;
this._pixelSnapping = pixelSnapping;
this._smoothing = smoothing;
}
}
}
};
return def;
}).call(this);

Просмотреть файл

@ -1,3 +1,144 @@
const BitmapDataDefinition = {
__class__: 'flash.display.BitmapData'
};
var BitmapDataDefinition = (function () {
var def = {
__class__: 'flash.display.BitmapData',
initialize: function () {
var s = this.symbol;
if (s) {
this.ctor(s.width, s.height);
this._ctx.drawImage(s.img, 0, 0);
}
},
_checkCanvas: function() {
if (this._drawable === null)
throw ArgumentError();
},
ctor : function(width, height, transparent, backgroundColor) {
if (isNaN(width + height) || width <= 0 || height <= 0)
throw ArgumentError();
this._transparent = !!transparent;
var canvas = document.createElement('canvas');
this._ctx = canvas.getContext('2d');
canvas.width = width | 0;
canvas.height = height | 0;
this._drawable = canvas;
this._backgroundColor = backgroundColor;
if (!transparent || backgroundColor | 0)
this.fillRect(new flash.geom.Rectangle(0, 0, width | 0, height | 0), backgroundColor);
},
dispose: function() {
this._ctx = null;
this._drawable.width = 0;
this._drawable.height = 0;
this._drawable = null;
},
draw : function(source, matrix, colorTransform, blendMode, clipRect) {
this._checkCanvas();
this._ctx.save();
this._ctx.beginPath();
this._ctx.rect(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
this._ctx.clip();
renderDisplayObject(source, this._ctx, matrix, colorTransform);
this._ctx.restore();
},
fillRect : function(rect, color) {
this._checkCanvas();
if (!this._transparent) {
color |= 0xff000000 >>> 0;
}
var ctx = this._ctx;
ctx.fillStyle = ARGBtoCSSColor(color);
ctx.fillRect(rect.x, rect.y, rect.width, rect.height);
},
getPixel : function(x, y) {
this._checkCanvas();
var data = this._ctx.getImageData(x, y, 1, 1);
return dataToRGB(data);
},
getPixel32 : function(x, y) {
this._checkCanvas();
var data = this._ctx.getImageData(x, y, 1, 1);
return dataToARGB(data);
},
setPixel : function(x, y, color) {
this.fillRect({ x: x, y: y, width: 1, height: 1 }, color | 0xFF000000);
},
setPixel32 : function(x, y, color) {
this.fillRect({ x: x, y: y, width: 1, height: 1 }, color);
},
clone : function() {
this._checkCanvas();
var bd = new flash.display.BitmapData(this._drawable.width, this._drawable.height, true, 0);
bd._ctx.drawImage(this._drawable, 0, 0);
return bd;
},
scroll : function(x, y) {
this._checkCanvas();
this._ctx.draw(this._drawable, x, y);
this._ctx.save();
this._ctx.fillStyle = ARGBtoCSSColor(this._backgroundColor);
var w = this._drawable.width;
var h = this._drawable.height;
if (x > 0) {
this._ctx.fillRect(0, 0, x, h);
} else if (x < 0) {
this._ctx.fillRect(x, 0, w, h);
}
if (y > 0) {
this._ctx.fillRect(x, y, w, h);
} else if (y < 0) {
this._ctx.fillRect(0, y, w, h);
}
this._ctx.restore();
},
get width() {
return this._drawable.width;
},
get height() {
return this._drawable.height;
},
};
var desc = Object.getOwnPropertyDescriptor;
def.__glue__ = {
native: {
instance: {
ctor : def.ctor,
fillRect : def.fillRect,
dispose : def.dispose,
getPixel : def.getPixel,
getPixel32 : def.getPixel32,
setPixel : def.setPixel,
setPixel32 : def.setPixel32,
draw : def.draw,
clone : def.clone,
scroll : def.scroll,
width : desc(def, "width"),
height : desc(def, "height"),
}
}
};
return def;
}).call(this);
function dataToRGB(data) {
return data[0] << 24 | data[1] << 16 | data[2];
}
function dataToARGB(data) {
return data[3] << 32 | dataToRGB(data);
}
function ARGBtoRGBA(argb) {
return (argb >>> 24 | argb << 8) >>> 0;
}
function ARGBtoCSSColor(argb) {
return 'rgba(' + (argb >>> 16 & 0xff) + ',' + (argb >>> 8 & 0xff) + ',' +
(argb & 0xff) + ',' + (argb >>> 24 & 0xff) / 0xff + ')';
}

Просмотреть файл

@ -1,4 +1,4 @@
const DisplayObjectDefinition = (function () {
var DisplayObjectDefinition = (function () {
var BLEND_MODE_ADD = 'add';
var BLEND_MODE_ALPHA = 'alpha';
var BLEND_MODE_DARKEN = 'darken';
@ -21,18 +21,26 @@ const DisplayObjectDefinition = (function () {
initialize: function () {
this._alpha = 1;
this._animated = false;
this._cacheAsBitmap = false;
this._control = document.createElement('div');
this._bbox = null;
this._bounds = null;
this._cacheAsBitmap = false;
this._children = [];
this._control = document.createElement('div');
this._clipDepth = 0;
this._currentTransform = null;
this._cxform = null;
this._dirtyArea = null;
this._graphics = null;
this._loaderInfo = null;
this._mouseChildren = true;
this._mouseOver = false;
this._mouseX = 0;
this._mouseY = 0;
this._name = null;
this._opaqueBackground = null;
this._owned = false;
this._parent = null;
this._revision = 0;
this._root = null;
this._rotation = 0;
this._scaleX = 1;
@ -42,12 +50,139 @@ const DisplayObjectDefinition = (function () {
this._visible = true;
this._x = 0;
this._y = 0;
this._updateTransformMatrix();
var s = this.symbol;
if (s) {
this._bbox = s.bbox || null;
this._children = s.children || [];
}
this._updateCurrentTransform();
},
_applyCurrentInverseTransform: function (point, targetCoordSpace) {
if (this._parent !== this._stage && this._parent !== targetCoordSpace)
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;
},
_applyCurrentTransform: function (point, targetCoordSpace) {
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 !== targetCoordSpace)
this._parent._applyCurrentTransform(point, targetCoordSpace);
},
_hitTest: function (use_xy, x, y, useShape, hitTestObject, ignoreChildren) {
if (use_xy) {
var pt = { x: x, y: y };
this._applyCurrentInverseTransform(pt);
if (useShape) {
if (this._graphics) {
var scale = this._graphics._scale;
if (scale !== 1) {
pt.x /= scale;
pt.y /= scale;
}
var subpaths = this._graphics._subpaths;
for (var i = 0, n = subpaths.length; i < n; i++) {
var pathTracker = subpaths[i];
var path = pathTracker.target;
var hitCtx = path.__hitContext__;
if (hitCtx.isPointInPath(pt.x, pt.y))
return true;
if (!path.strokeStyle)
continue;
var drawingStyles = pathTracker.drawingStyles;
if (hitCtx.mozIsPointInStroke) {
hitCtx.strokeStyle = path.strokeStyle;
for (var prop in drawingStyles)
hitCtx[prop] = drawingStyles[prop];
if (hitCtx.mozIsPointInStroke(pt.x, pt.y))
return true;
} else {
var strokeHitCtx = path._strokeHitContext;
if (!strokeHitCtx) {
var strokeHitCanvas = hitCtx.canvas.cloneNode();
strokeHitCtx = strokeHitCanvas.getContext('2d');
path._strokeHitContext = strokeHitCtx;
pathTracker.strokeToPath(strokeHitCtx, {
strokeWidth: drawingStyles.lineWidth,
startCap: drawingStyles.lineCap,
endCap: drawingStyles.lineCap,
join: drawingStyles.lineJoin,
miterLimit: drawingStyles.miterLimit
});
}
if (strokeHitCtx.isPointInPath(pt.x, pt.y))
return true;
}
}
}
if (!ignoreChildren) {
var children = this._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;
} else {
var b = this.getBounds();
return pt.x >= b.x && pt.x < b.x + b.width &&
pt.y >= b.y && pt.y < b.y + b.height;
}
}
var b1 = this.getBounds();
var b2 = hitTestObject.getBounds();
var x = Math.max(b1.x, b2.x);
var y = Math.max(b1.y, b2.y);
var width = Math.min(b1.x + b1.width, b2.x + b2.width) - x;
var height = Math.min(b1.y + b1.height, b2.y + b2.height) - y;
return width > 0 && height > 0;
},
_markAsDirty: function() {
if (!this._dirtyArea) {
this._dirtyArea = this.getBounds();
} else {
this._dirtyArea = this.getBounds().union(this._dirtyArea);
}
this._bounds = null;
},
_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
};
},
get accessibilityProperties() {
@ -81,83 +216,6 @@ const DisplayObjectDefinition = (function () {
set filters(val) {
notImplemented();
},
getBounds: function (targetCoordSpace) {
var bbox = this._bbox;
if (!bbox)
return new flash.geom.Rectangle;
var p1 = {x: bbox.left, y: bbox.top};
this._applyCurrentTransform(p1, targetCoordSpace);
var p2 = {x: bbox.right, y: bbox.top};
this._applyCurrentTransform(p2, targetCoordSpace);
var p3 = {x: bbox.right, y: bbox.bottom};
this._applyCurrentTransform(p3, targetCoordSpace);
var p4 = {x: bbox.left, y: bbox.bottom};
this._applyCurrentTransform(p4, targetCoordSpace);
var xMin = Math.min(p1.x, p2.x, p3.x, p4.x);
var xMax = Math.max(p1.x, p2.x, p3.x, p4.x);
var yMin = Math.min(p1.y, p2.y, p3.y, p4.y);
var yMax = Math.max(p1.y, p2.y, p3.y, p4.y);
return new flash.geom.Rectangle(
xMin,
yMin,
(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, targetCoordSpace) {
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 !== targetCoordSpace) {
this._parent._applyCurrentTransform(point, targetCoordSpace);
}
},
_applyCurrentInverseTransform: function (point, targetCoordSpace) {
if (this._parent !== this._stage && this._parent !== targetCoordSpace) {
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);
return result;
},
get height() {
var bounds = this.getBounds();
return bounds.height;
@ -165,30 +223,9 @@ const DisplayObjectDefinition = (function () {
set height(val) {
notImplemented();
},
hitTestObject: function (obj) {
return this._hitTest(false, 0, 0, false, obj);
},
hitTestPoint: function (x, y, shapeFlag) {
return this._hitTest(true, x, y, shapeFlag, null);
},
_hitTest: function _hitTest(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);
}
},
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;
},
@ -217,15 +254,18 @@ 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;
},
set rotation(val) {
this._markAsDirty();
this._rotation = val;
this._updateTransformMatrix();
this._slave = false;
this._updateCurrentTransform();
},
get stage() {
return this._stage || (this._parent ? this._parent.stage : null);
@ -234,17 +274,23 @@ const DisplayObjectDefinition = (function () {
return this._scaleX;
},
set scaleX(val) {
this._markAsDirty();
this._scaleX = val;
this._updateTransformMatrix();
this._slave = false;
this._updateCurrentTransform();
},
get scaleY() {
return this._scaleY;
},
set scaleY(val) {
this._markAsDirty();
this._scaleY = val;
this._updateTransformMatrix();
this._slave = false;
this._updateCurrentTransform();
},
get scale9Grid() {
return null;
@ -262,45 +308,152 @@ const DisplayObjectDefinition = (function () {
return this._transform || new flash.geom.Transform(this);
},
set transform(val) {
this._currentTransform = val.matrix;
this._slave = false;
var transform = this._transform;
transform.colorTransform = val.colorTransform;
transform.matrix = val.matrix;
this._currentTransformMatrix = val.matrix;
this._slave = false;
this._markAsDirty();
},
get visible() {
return this._visible;
},
set visible(val) {
this._visible = val;
this._slave = false;
this._visible = val;
this._markAsDirty();
},
get width() {
var bounds = this.getBounds();
return bounds.width;
},
set width(val) {
//notImplemented();
notImplemented();
},
get x() {
return this._x;
},
set x(val) {
this._x = val;
this._updateTransformMatrix();
this._markAsDirty();
this._slave = false;
this._x = val;
this._updateCurrentTransform();
},
get y() {
return this._y;
},
set y(val) {
this._y = val;
this._updateTransformMatrix();
this._markAsDirty();
this._slave = false;
this._y = val;
this._updateCurrentTransform();
},
getBounds: function (targetCoordSpace) {
if (this._bounds)
return this._bounds;
var bbox = this._bbox;
var xMin = Number.MAX_VALUE;
var xMax = Number.MIN_VALUE;
var yMin = Number.MAX_VALUE;
var yMax = Number.MIN_VALUE;
if (!bbox) {
var children = this._children;
var numChildren = children.length;
var b;
for (var i = 0; i < numChildren; i++) {
var child = children[i];
var b = child.getBounds(this);
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);
}
} else {
xMin = bbox.left;
xMax = bbox.right;
yMin = bbox.top;
yMax = bbox.bottom;
}
if (this._graphics) {
var b = this._graphics._getBounds(true);
if (b) {
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);
}
}
if (xMin === Number.MAX_VALUE) {
return new flash.geom.Rectangle();
}
var p1 = { x: xMin, y: yMin };
this._applyCurrentTransform(p1, targetCoordSpace);
var p2 = { x: xMax, y: yMin };
this._applyCurrentTransform(p2, targetCoordSpace);
var p3 = { x: xMax, y: yMax };
this._applyCurrentTransform(p3, targetCoordSpace);
var p4 = { x: xMin, y: yMax };
this._applyCurrentTransform(p4, targetCoordSpace);
xMin = Math.min(p1.x, p2.x, p3.x, p4.x);
xMax = Math.max(p1.x, p2.x, p3.x, p4.x);
yMin = Math.min(p1.y, p2.y, p3.y, p4.y);
yMax = Math.max(p1.y, p2.y, p3.y, p4.y);
return new flash.geom.Rectangle(
xMin,
yMin,
(xMax - xMin),
(yMax - yMin)
);
},
getRect: function (targetCoordSpace) {
notImplemented();
},
globalToLocal: function (pt) {
var result = new flash.geom.Point(pt.x, pt.y);
this._applyCurrentInverseTransform(result);
return result;
},
hitTestObject: function (obj) {
return this._hitTest(false, 0, 0, false, obj);
},
hitTestPoint: function (x, y, shapeFlag) {
return this._hitTest(true, x, y, shapeFlag, null);
},
localToGlobal: function (pt) {
var result = new flash.geom.Point(pt.x, pt.y);
this._applyCurrentTransform(result);
return result;
}
};
const desc = Object.getOwnPropertyDescriptor;
var desc = Object.getOwnPropertyDescriptor;
def.__glue__ = {
native: {

Просмотреть файл

@ -1,14 +1,10 @@
const DisplayObjectContainerDefinition = (function () {
var DisplayObjectContainerDefinition = (function () {
var def = {
initialize: function () {
this._children = [];
},
get mouseChildren() {
return true;
return this._mouseChildren;
},
set mouseChildren(val) {
notImplemented();
this._mouseChildren = val;
},
get numChildren() {
return this._children.length;
@ -45,6 +41,10 @@ const DisplayObjectContainerDefinition = (function () {
child._owned = false;
child._parent = this;
this._control.appendChild(child._control);
this._markAsDirty();
return child;
},
areInaccessibleObjectsUnderPoint: function (pt) {
@ -100,6 +100,10 @@ const DisplayObjectContainerDefinition = (function () {
children.splice(index, 1);
child._parent = null;
this._control.removeChild(child._control);
this._markAsDirty();
return child;
},
setChildIndex: function (child, index) {
@ -117,6 +121,8 @@ const DisplayObjectContainerDefinition = (function () {
children.splice(index, 0, child);
child._owned = false;
this._markAsDirty();
return child;
},
removeChildren: function (begin, end) {
@ -152,50 +158,12 @@ 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
};
this._markAsDirty();
}
};
const desc = Object.getOwnPropertyDescriptor;
var desc = Object.getOwnPropertyDescriptor;
def.__glue__ = {
native: {

Просмотреть файл

@ -1,4 +1,4 @@
const GraphicsDefinition = (function () {
var GraphicsDefinition = (function () {
var GRAPHICS_PATH_COMMAND_CUBIC_CURVE_TO = 6;
var GRAPHICS_PATH_COMMAND_CURVE_TO = 3;
var GRAPHICS_PATH_COMMAND_LINE_TO = 2;
@ -25,42 +25,13 @@ const GraphicsDefinition = (function () {
this._drawingStyles = null;
this._fillStyle = null;
this._fillTransform = null;
this._revision = 0;
this._scale = 1;
this._strokeStyle = null;
this._subpaths = [];
},
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 {
@ -92,7 +63,7 @@ const GraphicsDefinition = (function () {
}
}
},
beginStrokeObject: function (istroke) {
_beginStrokeObject: function (istroke) {
var stroke = null;
var fill = null;
@ -148,6 +119,64 @@ 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;
var pathTracker = new PolygonTracker(path);
pathTracker.drawingStyles = this._drawingStyles;
path.fillStyle = this._fillStyle;
path.fillTransform = this._fillTransform;
path.strokeStyle = this._strokeStyle;
this._subpaths.push(pathTracker);
// Cache as an own property.
Object.defineProperty(this, '_currentPath', describeProperty(pathTracker));
return pathTracker;
},
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(-1, 0, 1, 0);
else if (type == 'radial')
gradient = fillContext.createRadialGradient((focalPos || 0), 0, 0, 0, 0, 1);
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;
// NOTE firefox really sensitive to really small scale when painting gradients
var scale = 819.2;
this._fillTransform = matrix ?
{ a: scale * matrix.a, b: scale * matrix.b, c: scale * matrix.c, d: scale * matrix.d, tx: matrix.tx, ty: matrix.ty } :
{ a: scale, b: 0, c: 0, d: scale, tx: 0, ty: 0 };
},
beginBitmapFill: function (bitmap, matrix, repeat, smooth) {
var repeatStyle = repeat ? 'repeat' : 'no-repeat';
this._fillStyle = fillContext.createPattern(bitmap._drawable, repeatStyle);
var scale = this._scale;
this._fillTransform = matrix ?
{ a: scale * matrix.a, b: scale * matrix.b, c: scale * matrix.c, d: scale * matrix.d, tx: matrix.tx, ty: matrix.ty } :
{ a: scale, b: 0, c: 0, d: scale, tx: 0, ty: 0 };
},
clear: function () {
delete this._currentPath;
@ -162,19 +191,21 @@ const GraphicsDefinition = (function () {
},
cubicCurveTo: function (cp1x, cp1y, cp2x, cp2y, x, y) {
this._currentPath.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
this._revision++;
},
curveTo: function (cpx, cpy, x, y) {
this._currentPath.quadraticCurveTo(cpx, cpy, x, y);
this._revision++;
},
drawGraphicsData: function (graphicsData) {
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) {
@ -202,29 +233,44 @@ 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();
this._currentPath.rect(x, y, w, h);
this._revision++;
},
drawRoundRect: function (x, y, w, h, ellipseWidth, ellipseHeight) {
if (isNaN(w + h + ellipseWidth) || (ellipseHeight !== undefined && isNaN(ellipseHeight)))
throw ArgumentError();
notImplemented();
var radiusW = ellipseWidth / 2;
var radiusH = ellipseHeight / 2;
// A-----B
// H C
// G D
// F-----E
//
// Through some testing, it has been discovered
// tha the Flash player starts and stops the pen
// at 'D', so we will too.
this._currentPath.moveTo(x+w, y+h-radiusH);
this._currentPath.arcTo(x+w, y+h, x+w-radiusW, y+h-radiusH, radiusW, radiusH);
this._currentPath.arcTo(x, y+h, x, y+h-radiusH, radiusW, radiusH);
this._currentPath.arcTo(x, y, x+radiusW, y, radiusW, radiusH);
this._currentPath.arcTo(x+w, y, x+w, y+radiusH, radiusW, radiusH);
},
drawRoundRectComplex: function (x, y, w, h, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius) {
if (isNaN(h + topLeftRadius + topRightRadius + bottomLeftRadius + bottomRightRadius))
if (isNaN(w + h + topLeftRadius + topRightRadius + bottomLeftRadius + bottomRightRadius))
throw ArgumentError();
notImplemented();
this._currentPath.moveTo(x+w, y+h-radiusH);
this._currentPath.arcTo(x+w, y+h, x+w-bottomRightRadius, y+h-bottomRightRadius, bottomRightRadius);
this._currentPath.arcTo(x, y+h, x, y+h-bottomLeftRadius, bottomLeftRadius);
this._currentPath.arcTo(x, y, x+topLeftRadius, y, topLeftRadius);
this._currentPath.arcTo(x+w, y, x+w, y+topRightRadius, topRightRadius);
},
drawTriangles: function (vertices, indices, uvtData, culling) {
notImplemented();
@ -255,7 +301,7 @@ const GraphicsDefinition = (function () {
lineCap: cap || 'round',
lineJoin: cap || 'round',
lineWidth: width,
miterLimit: mlimit
miterLimit: mlimit * 2
};
this._strokeStyle = toRgba(color, alpha);
} else {
@ -263,26 +309,445 @@ const GraphicsDefinition = (function () {
this._strokeStyle = null;
}
},
moveTo: function (x, y) {
this._currentPath.moveTo(x, y);
},
lineTo: function (x, y) {
this._currentPath.lineTo(x, y);
this._revision++;
},
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;
moveTo: function (x, y) {
this._currentPath.moveTo(x, y);
this._revision++;
},
_getBounds: function (includeStroke) {
var subpaths = this._subpaths;
var xMins = [], yMins = [], xMaxs = [], yMaxs = [];
for (var i = 0, n = subpaths.length; i < n; i++) {
var pathTracker = subpaths[i];
var b = pathTracker.getBounds();
if (b) {
xMins.push(b.minX); yMins.push(b.minY); xMaxs.push(b.maxX); yMaxs.push(b.maxY);
}
if (includeStroke && pathTracker.target.strokeStyle) {
var strokeTracker = new PolygonTracker();
var drawingStyles = pathTracker.drawingStyles;
pathTracker.strokeToPath(strokeTracker, {
strokeWidth: drawingStyles.lineWidth,
startCap: drawingStyles.lineCap,
endCap: drawingStyles.lineCap,
join: drawingStyles.lineJoin,
miterLimit: drawingStyles.miterLimit
});
var b = strokeTracker.getBounds();
if (b) {
xMins.push(b.minX); yMins.push(b.minY); xMaxs.push(b.maxX); yMaxs.push(b.maxY);
}
}
}
if (xMins.length === 0) {
return 0;
}
var scale = this._scale;
var xMin = Math.min.apply(Math, xMins) * scale;
var yMin = Math.min.apply(Math, yMins) * scale;
var xMax = Math.max.apply(Math, xMaxs) * scale;
var yMax = Math.max.apply(Math, yMaxs) * scale;
return { x: xMin, y: yMin, width: xMax - xMin, height: yMax - yMin};
}
};
var PolygonTracker = (function PolygonTrackerClosure() {
var CURVE_APPROX_POINTS = 8;
var CIRCLE_APPROX_POINTS = 12; // per PI
var CIRCLE_APPROX_SIN = Math.sin(Math.PI / CIRCLE_APPROX_POINTS);
var CIRCLE_APPROX_COS = Math.cos(Math.PI / CIRCLE_APPROX_POINTS);
function strokeToPath(tracker, options, output) {
function buildCap(lines, capStyle, line1, line2) {
line1.type = 3;
switch (capStyle) {
case 'round':
var cx = (line1.x2 + line2.x1) / 2;
var cy = (line1.y2 + line2.y1) / 2;
var dx = (line1.x2 - cx), dy = (line1.y2 - cy);
for (var i = 0; i < CIRCLE_APPROX_POINTS; i++) {
var dx1 = dx * CIRCLE_APPROX_COS - dy * CIRCLE_APPROX_SIN;
var dy1 = dx * CIRCLE_APPROX_SIN + dy * CIRCLE_APPROX_COS;
lines.push({
x1: cx + dx, y1: cy + dy,
x2: cx + dx1, y2: cy + dy1,
type: 3});
dx = dx1; dy = dy1;
}
break;
case 'square':
var capHeight = options.strokeWidth / 2;
var dx = line1.x2 - line1.x1, dy = line1.y2 - line1.y1;
var d = Math.sqrt(dx * dx + dy * dy);
line1.x2 += dx * capHeight / d;
line1.y2 += dy * capHeight / d;
line2.x1 += dx * capHeight / d;
line2.y1 += dy * capHeight / d;
// fall throw
case 'none':
default:
lines.push({
x1: line1.x2, y1: line1.y2,
x2: line2.x1, y2: line2.y1,
type: 3});
break;
}
}
function joinLines(cmds, line1, line2, type) {
// (x - x1) * (y2 - y1) - (y - y1) * (x2 - x1) = 0, a*x + b*y = c
var a1 = (line1.y2 - line1.y1), b1 = -(line1.x2 - line1.x1), c1 = line1.x1 * line1.y2 - line1.x2 * line1.y1;
var a2 = (line2.y2 - line2.y1), b2 = -(line2.x2 - line2.x1), c2 = line2.x1 * line2.y2 - line2.x2 * line2.y1;
var d = a1 * b2 - b1 * a2;
if (d == 0) {
// parellel lines doing bevel
cmds.push({type: 'lineTo', args: [line1.x2, line1.y2]});
cmds.push({type: 'lineTo', args: [line2.x1, line2.y1]});
return;
}
var x = (c1 * b2 - b1 * c2) / d;
var y = (a1 * c2 - c1 * a2) / d;
var onLine1 = !(
(x < line1.x1 && x < line1.x2) || (x > line1.x1 && x > line1.x2) ||
(y < line1.y1 && y < line1.y2) || (y > line1.y1 && y > line1.y2));
var onLine2 = !(
(x < line2.x1 && x < line2.x2) || (x > line2.x1 && x > line2.x2) ||
(y < line2.y1 && y < line2.y2) || (y > line2.y1 && y > line2.y2));
if (!onLine1 && !onLine2) {
switch (type) {
default:
case 'bevel':
cmds.push({type: 'lineTo', args: [line1.x2, line1.y2]});
cmds.push({type: 'lineTo', args: [line2.x1, line2.y1]});
break;
case 'round':
cmds.push({type: 'lineTo', args: [line1.x2, line1.y2]});
cmds.push({type: 'quadraticCurveTo', args: [x, y, line2.x1, line2.y1]});
break;
case 'miter':
cmds.push({type: 'lineTo', args: [line1.x2, line1.y2]});
var a = -(line1.y2 - line2.y1), b = line1.x2 - line2.x1;
var d = Math.sqrt(a * a + b * b);
var miterLength = (a * (x - line2.x1) + b * (y - line2.y1)) / d;
var maxAllowedLength = options.miterLimit * options.strokeWidth / 2;
if (miterLength > maxAllowedLength) {
var p2 = maxAllowedLength / miterLength, p1 = 1 - p2;
cmds.push({type: 'lineTo', args: [line1.x2 * p1 + x * p2, line1.y2 * p1 + y * p2]});
cmds.push({type: 'lineTo', args: [line2.x1 * p1 + x * p2, line2.y1 * p1 + y * p2]});
} else {
cmds.push({type: 'lineTo', args: [x, y]});
}
cmds.push({type: 'lineTo', args: [line2.x1, line2.y1]});
break;
}
} else if (!onLine1 || !onLine2) {
cmds.push({type: 'lineTo', args: onLine1 ? [x, y] : [line1.x2, line1.y2]});
cmds.push({type: 'lineTo', args: onLine2 ? [x, y] : [line2.x1, line2.y1]});
} else {
cmds.push({type: 'lineTo', args: [x, y]});
}
}
function buildPath(lines) {
var moveCmd = {type: 'moveTo', args: null};
var cmds = [moveCmd];
var joinType = options.join;
for (var j = 0; j < lines.length; j++) {
var type = lines[j].type;
switch (type) {
default:
joinLines(cmds, lines[j], lines[(j + 1) % lines.length], joinType);
break;
case 3: // simple line
cmds.push({type: 'lineTo', args: [lines[j].x2, lines[j].y2]});
break;
case 4: // curve segment connector
joinLines(cmds, lines[j], lines[(j + 1) % lines.length], 'bevel');
break;
}
}
moveCmd.args = cmds[cmds.length - 1].args.slice(-2);
cmds.push({type: 'closePath'});
for (var i = 0; i < cmds.length; i++) {
output[cmds[i].type].apply(output, cmds[i].args);
}
}
var i = 0;
var segments = tracker.segments;
var points = tracker.points;
var start = segments[0];
do {
++i;
var end = i < segments.length ? segments[i] : points.length;
if (points[start].type !== 0) {
throw 'invalid points structure';
}
if (start + 1 >= end) {
// only moveTo operation
end = start;
continue;
}
var pathClosed = points[end - 1].type === 2;
var lastX = points[start].x;
var lastY = points[start].y;
var lastType = 0;
start++;
// building paths
var forward = [], backward = [];
var strokeHalfWidth = options.strokeWidth / 2;
for (var j = start; j < end; j++) {
var x = points[j].x, y = points[j].y, type = points[j].type;
var dx = x - lastX;
var dy = y - lastY;
if (dx == 0 && dy == 0) continue;
var k = strokeHalfWidth / Math.sqrt(dx * dx + dy * dy);
dx *= k; dy *= k;
forward.push({
x1: lastX + dy, y1: lastY - dx,
x2: x + dy, y2: y - dx,
type: type
});
backward.push({
x1: x - dy, y1: y + dx,
x2: lastX - dy, y2: lastY + dx,
type: lastType
});
lastX = x; lastY = y; lastType = type;
}
backward.reverse();
if (!pathClosed) {
buildCap(forward, options.endCap, forward[forward.length - 1], backward[0]);
buildCap(backward, options.startCap, backward[backward.length - 1], forward[0]);
forward = forward.concat(backward);
buildPath(forward);
} else {
buildPath(forward);
buildPath(backward);
}
start = end;
} while (i < segments.length);
}
function pushCurveApprox(points, x1, y1, x2, y2) {
var x0 = points[points.length - 1].x;
var y0 = points[points.length - 1].y;
for (var i = 0; i < CURVE_APPROX_POINTS; i++) {
var p2 = (i + 1) / CURVE_APPROX_POINTS, p1 = 1 - p2;
var x01 = x0 * p1 + x1 * p2, y01 = y0 * p1 + y1 * p2;
var x12 = x1 * p1 + x2 * p2, y12 = y1 * p1 + y2 * p2;
var x = x01 * p1 + x12 * p2, y = y01 * p1 + y12 * p2;
points.push({x: x, y: y, type: 4});
}
points[points.length - 1].type = 1;
}
function pushBezierCurveApprox(points, x1, y1, x2, y2, x3, y3) {
var x0 = points[points.length - 1].x;
var y0 = points[points.length - 1].y;
for (var i = 0; i < CURVE_APPROX_POINTS; i++) {
var p2 = (i + 1) / CURVE_APPROX_POINTS, p1 = 1 - p2;
var x01 = x0 * p1 + x1 * p2, y01 = y0 * p1 + y1 * p2;
var x12 = x1 * p1 + x2 * p2, y12 = y1 * p1 + y2 * p2;
var x23 = x2 * p1 + x3 * p2, y23 = y2 * p1 + y3 * p2;
var x012 = x01 * p1 + x12 * p2, y012 = y01 * p1 + y12 * p2;
var x123 = x12 * p1 + x23 * p2, y123 = y12 * p1 + y23 * p2;
var x = x012 * p1 + x123 * p2, y = y012 * p1 + y123 * p2;
points.push({x: x, y: y, type: 4});
}
points[points.length - 1].type = 1;
}
function normalizeAngle(angle) {
while (angle > Math.PI)
angle -= 2 * Math.PI;
while (angle <= -Math.PI)
angle += 2 * Math.PI;
return angle;
}
function pushArcApprox(points, x1, y1, x2, y2, radiusX, radiusY, rotation) {
var x0 = points[points.length - 1].x;
var y0 = points[points.length - 1].y;
var dx01 = x1 - x0, dy01 = y1 - y0, dx12 = x2 - x1, dy12 = y2 - y1;
var winding = dx01 * dy12 - dy01 * dx12;
// if radiusX or radiusY == 0, or points #0, #1, and #2 are on one line,
// just draw simple line to point #1
if (radiusX <= 0 || radiusY <= 0 || winding == 0) {
points.push({x: x1, y: y1, type: 1});
return;
}
var rotationCos = 1, rotationSin = 0;
if (rotation) {
rotationCos = Math.cos(rotation);
rotationSin = Math.sin(rotation);
}
// placing major axis to x
var dx01_ = dx01 * rotationCos + dy01 * rotationSin;
var dy01_ = -dx01 * rotationSin + dy01 * rotationCos;
var dx12_ = dx12 * rotationCos + dy12 * rotationSin;
var dy12_ = -dx12 * rotationSin + dy12 * rotationCos;
var alpha1 = Math.atan2(-dx01_ * radiusY, dy01_ * radiusX);
var alpha2 = Math.atan2(-dx12_ * radiusY, dy12_ * radiusX);
if (winding < 0) {
alpha1 = (alpha1 >= 0 ? -Math.PI : Math.PI) + alpha1;
alpha2 = (alpha2 >= 0 ? -Math.PI : Math.PI) + alpha2;
}
// start and end offsets of the arc from center
var bx1_ = radiusX * Math.cos(alpha1), by1_ = radiusY * Math.sin(alpha1);
var bx2_ = radiusX * Math.cos(alpha2), by2_ = radiusY * Math.sin(alpha2);
var bx1 = bx1_ * rotationCos - by1_ * rotationSin;
var by1 = bx1_ * rotationSin + by1_ * rotationCos;
var bx2 = bx2_ * rotationCos - by2_ * rotationSin;
var by2 = bx2_ * rotationSin + by2_ * rotationCos;
// finding center
// (x1 - bx1 - cx) * (y1 - y0) - (y1 - by1 - cy) * (x1 - x0) = 0
var a1 = y1 - y0, b1 = -(x1 - x0), c1 = (x1 - bx1) * (y1 - y0) - (y1 - by1) * (x1 - x0);
var a2 = y2 - y1, b2 = -(x2 - x1), c2 = (x2 - bx2) * (y2 - y1) - (y2 - by2) * (x2 - x1);
var d = a1 * b2 - b1 * a2;
var cx = (c1 * b2 - b1 * c2) / d;
var cy = (a1 * c2 - c1 * a2) / d;
points.push({x: bx1 + cx, y: by1 + cy, type: 1}); // line from point #0
// building arc segments
var angleDistance = normalizeAngle(alpha2 - alpha1);
var stepsCount = Math.ceil(Math.abs(angleDistance) / Math.PI * CIRCLE_APPROX_POINTS);
var step = angleDistance / stepsCount;
for (var i = 1; i <= stepsCount; i++) {
var alpha = alpha1 + (angleDistance * i / stepsCount);
var x_ = radiusX * Math.cos(alpha), y_ = radiusY * Math.sin(alpha);
var x = x_ * rotationCos - y_ * rotationSin + cx;
var y = x_ * rotationSin + y_ * rotationCos + cy;
points.push({x: x, y: y, type: 4});
}
points[points.length - 1].type = 1;
}
function PolygonTrackerNullOutput() {}
PolygonTrackerNullOutput.prototype = {
moveTo: function () {},
lineTo: function () {},
quadraticCurveTo: function () {},
closePath: function () {}
};
function PolygonTracker(target) {
this.target = target || new PolygonTrackerNullOutput;
this.segments = [0];
this.points = [{x: 0, y: 0, type: 0}];
}
PolygonTracker.prototype = {
get lineWidth() {
return this.target.lineWidth;
},
set lineWidth(value) {
this.target.lineWidth = value;
},
get lineCap() {
return this.target.lineCap;
},
set lineCap(value) {
this.target.lineCap = value;
},
get lineJoin() {
return this.target.lineJoin;
},
set lineJoin(value) {
this.target.lineJoin = value;
},
get miterLimit() {
return this.target.miterLimit;
},
set miterLimit(value) {
this.target.miterLimit = value;
},
moveTo: function (x, y) {
var segmentStartIndex = this.segments[this.segments.length - 1];
if (segmentStartIndex === this.points.length - 1) {
this.points[segmentStartIndex].x = x;
this.points[segmentStartIndex].y = y;
} else {
this.segments.push(this.points.length);
this.points.push({x: x, y: y, type: 0});
}
this.target.moveTo(x, y);
},
lineTo: function (x, y) {
this.points.push({x: x, y: y, type: 1});
this.target.lineTo(x, y);
},
closePath: function () {
var segmentStartIndex = this.segments[this.segments.length - 1];
this.points.push({x: this.points[segmentStartIndex].x,
y: this.points[segmentStartIndex].y,
type: 2});
this.target.closePath();
this.segments.push(this.points.length);
this.points.push({x: this.points[segmentStartIndex].x,
y: this.points[segmentStartIndex].y,
type: 0});
},
quadraticCurveTo: function (cpx, cpy, x, y) {
pushCurveApprox(this.points, cpx, cpy, x, y);
this.target.quadraticCurveTo(cpx, cpy, x, y);
},
bezierCurveTo: function (cpx1, cpy1, cpx2, cpy2, x, y) {
pushBezierCurveApprox(this.points, cpx1, cpy1, cpx2, cpy2, x, y);
this.target.bezierCurveTo(cpx1, cpy1, cpx2, cpy2, x, y);
},
arcTo: function (x1, y1, x2, y2, radiusX, radiusY, rotation) {
pushArcApprox(this.points, x1, y1, x2, y2, radiusX,
arguments.length < 6 ? radiusX : radiusY,
rotation);
this.target.arcTo.apply(this.target, arguments);
},
rect: function (x, y, w, h) {
var segmentStartIndex = this.segments[this.segments.length - 1];
if (segmentStartIndex === this.points.length - 1) {
this.points[segmentStartIndex].x = x;
this.points[segmentStartIndex].y = y;
} else {
this.segments.push(this.points.length);
this.points.push({x: x, y: y, type: 0});
}
this.points.push({x: x + w, y: y, type: 1});
this.points.push({x: x + w, y: y + h, type: 1});
this.points.push({x: x, y: y + h, type: 1});
this.points.push({x: x, y: y, type: 2});
this.target.rect(x, y, w, h);
},
strokeToPath: function (output, options) {
strokeToPath(this, options || {
strokeWidth: this.lineWidth,
startCap: this.lineCap,
endCap: this.lineCap,
join: this.lineJoin,
miterLimit: this.miterLimit
}, output);
},
getBounds: function () {
var points = this.points;
if (points.length <= 1) { // HACK only moveTo
return null;
}
var minX, minY, maxX, maxY;
minX = maxX = points[0].x;
minY = maxY = points[0].y;
for (var i = 1; i < points.length; i++) {
var x = points[i].x, y = points[i].y;
if (x < minX) minX = x;
if (y < minY) minY = y;
if (x > maxX) maxX = x;
if (y > maxY) maxY = y;
}
return {minX: minX, minY: minY, maxX: maxX, maxY: maxY};
}
};
return PolygonTracker;
})();
def.__glue__ = {
native: {
instance: {

Просмотреть файл

@ -1,7 +1,10 @@
const InteractiveObjectDefinition = (function () {
var InteractiveObjectDefinition = (function () {
var def = {
initialize: function () {
this._control = document.createElement('div');
this._doubleClickEnabled = false;
this._hitArea = null;
this._mouseEnabled = true;
},
get accessibilityImplementation() {
@ -17,10 +20,10 @@ const InteractiveObjectDefinition = (function () {
notImplemented();
},
get doubleClickEnabled() {
return false;
return this._doubleClickEnabled;
},
set doubleClickEnabled(val) {
notImplemented();
this._doubleClickEnabled = val;
},
get focusRect() {
return null;
@ -29,10 +32,10 @@ const InteractiveObjectDefinition = (function () {
notImplemented();
},
get mouseEnabled() {
return true;
return this._mouseEnabled;
},
set mouseEnabled(val) {
// notImplemented();
this._mouseEnabled = val;
},
get needsSoftKeyboard() {
return false;
@ -40,9 +43,6 @@ const InteractiveObjectDefinition = (function () {
set needsSoftKeyboard(val) {
notImplemented();
},
requestSoftKeyboard: function () {
notImplemented();
},
get softKeyboardInputAreaOfInterest() {
return null;
},
@ -57,12 +57,17 @@ const InteractiveObjectDefinition = (function () {
},
get tabIndex() {
return -1;
},
requestSoftKeyboard: function () {
notImplemented();
}
};
const desc = Object.getOwnPropertyDescriptor;
var desc = Object.getOwnPropertyDescriptor;
def.__glue__ = {
native: {
instance: {
tabEnabled: desc(def, "tabEnabled"),
tabIndex: desc(def, "tabIndex"),
@ -75,6 +80,7 @@ const InteractiveObjectDefinition = (function () {
contextMenu: desc(def, "contextMenu"),
requestSoftKeyboard: def.requestSoftKeyboard
}
}
};
return def;

Просмотреть файл

@ -1,7 +1,7 @@
const LoaderDefinition = (function () {
const WORKERS_ENABLED = true;
const LOADER_PATH = 'src/flash/display/Loader.js';
const WORKER_SCRIPTS = [
var LoaderDefinition = (function () {
var WORKERS_ENABLED = true;
var LOADER_PATH = 'flash/display/Loader.js';
var WORKER_SCRIPTS = [
'../../../lib/DataView.js/DataView.js',
'../util.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) {
@ -77,21 +77,29 @@ 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' };
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,7 +121,7 @@ const LoaderDefinition = (function () {
i++;
repeat++;
}
if (repeat > 1)
frameIndex += repeat;
frame.repeat = repeat;
frame.depths = depths;
frames.push(frame);
@ -126,7 +134,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:
@ -146,7 +155,6 @@ const LoaderDefinition = (function () {
symbols[swfTag.id] = symbol;
commitData(symbol);
}
function parseBytes(bytes) {
var depths = { };
var frame = { type: 'frame' };
@ -174,21 +182,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;
@ -221,7 +228,6 @@ const LoaderDefinition = (function () {
tagsProcessed++;
repeat++;
}
if (repeat > 1)
frame.repeat = repeat;
frame.depths = depths;
commitData(frame);
@ -287,28 +293,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"));
@ -318,14 +310,16 @@ 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 actionBlocks = frame.actionBlocks;
var initActionBlocks = frame.initActionBlocks;
var depths = frame.depths;
var exports = frame.exports;
var loader = this;
@ -353,8 +347,10 @@ const LoaderDefinition = (function () {
if (frame.bgcolor)
loaderInfo._backgroundColor = frame.bgcolor;
else
loaderInfo._backgroundColor = { color: 0xFFFFFF, alpha: 0xFF };
var i = frame.repeat || 1;
var i = frame.repeat;
while (i--)
timeline.push(framePromise);
@ -367,7 +363,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];
@ -387,8 +383,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);
@ -404,10 +400,15 @@ const LoaderDefinition = (function () {
loader._content = root;
}
framePromise.resolve(displayList);
root._framesLoaded++;
if (!loader._isAvm2Enabled) {
loader._initAvm1Bindings(root, needRootObject, frameNum,
actionBlocks, initActionBlocks, exports);
}
if (labelName) {
framePromise.resolve(displayList);
root._framesLoaded += frame.repeat;
if (labelName && root._frameLabels) {
root._frameLabels[labelName] = {
__class__: 'flash.display.FrameLabel',
frame: frameNum,
@ -419,11 +420,61 @@ const LoaderDefinition = (function () {
loaderInfo.dispatchEvent(new flash.events.Event('init'));
});
},
commitSymbol: function (symbol) {
_initAvm1Bindings: function(root, initializeRoot, frameNum,
actionBlocks, initActionBlocks, 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 rootAS2Object = root._getAS2Object();
rootAS2Object.soundmc = new SoundMock(exports);
var soundClass = avm2.systemDomain.getClass("flash.display.MovieClip");
var soundMock = soundClass.createInstance();
soundMock._name = 'soundmc';
soundMock._timeline = [new Promise];
soundMock._timeline[0].resolve([]);
soundMock._exports = exports;
soundMock.$as2Object = rootAS2Object.soundmc;
root.addChild(soundMock);
}
if (initActionBlocks) {
// HACK using symbol init actions as regular action blocks, the spec has a note
// "DoAction tag is not the same as specifying them in a DoInitAction tag"
for (var symbolId in initActionBlocks) {
root.addFrameScript(frameNum - 1, function(actionBlock) {
return executeActions(actionBlock, avm1Context, avm1Context.globals._root, exports);
}.bind(root, initActionBlocks[symbolId]));
}
}
if (actionBlocks) {
for (var i = 0; i < actionBlocks.length; i++) {
root.addFrameScript(frameNum - 1, function(actionBlock) {
return executeActions(actionBlock, avm1Context, avm1Context.globals._root, exports);
}.bind(root, actionBlocks[i]));
}
}
},
_commitSymbol: function (symbol) {
var dependencies = symbol.require;
var dictionary = this._dictionary;
var promiseQueue = [];
var symbolInfo = {};
var symbolInfo = { };
var symbolPromise = new Promise;
if (dependencies && dependencies.length) {
@ -437,7 +488,37 @@ const LoaderDefinition = (function () {
switch (symbol.type) {
case 'button':
var states = { };
for (var stateName in symbol.states) {
var children = [];
var depths = symbol.states[stateName];
for (var depth in depths) {
var cmd = depths[depth];
if (cmd && cmd.symbolId) {
var childPromise = dictionary[cmd.symbolId];
if (childPromise && !childPromise.resolved)
promiseQueue.push(childPromise);
}
children.push(childPromise);
}
if (children.length === 1) {
states[stateName] = children[0];
} else {
var statePromise = new Promise;
stateInfo = { };
stateInfo.className = 'flash.display.Sprite';
stateInfo.props = { children: children };
statePromise.resolve(stateInfo);
states[stateName] = statePromise;
}
}
symbolInfo.className = 'flash.display.SimpleButton';
symbolInfo.props = {
states: states
};
break;
case 'font':
var charset = fromCharCode.apply(null, symbol.codes);
@ -462,14 +543,20 @@ const LoaderDefinition = (function () {
imgPromise.resolve();
};
img.src = 'data:' + symbol.mimeType + ';base64,' + btoa(symbol.data);
promiseQueue.push(imgPromise);
symbolInfo.className = 'flash.display.BitmapData';
symbolInfo.props = { img: describeProperty(img) };
symbolInfo.props = {
img: img,
width: symbol.width,
height: symbol.height
};
break;
case 'label':
var drawFn = new Function('d,c,r', symbol.data);
symbolInfo.className = 'flash.text.StaticText';
symbolInfo.props = {
bbox: symbol.bbox,
draw: function (c, r) {
return drawFn.call(this, dictionary, c, r);
}
@ -479,29 +566,32 @@ const LoaderDefinition = (function () {
var drawFn = new Function('d,c,r', symbol.data);
symbolInfo.className = 'flash.text.TextField';
symbolInfo.props = {
bbox: symbol.bbox,
draw: function (c, r) {
return drawFn.call(this, dictionary, c, r);
},
text: symbol.value
text: symbol.value,
variableName: symbol.variableName
};
break;
case 'shape':
var bbox = symbol.bbox;
var createGraphicsData = new Function('d,r', 'return ' + symbol.data);
var graphics = new flash.display.Graphics;
graphics._scale = 0.05;
graphics.drawGraphicsData(createGraphicsData(dictionary, 0));
symbolInfo.className = 'flash.display.Shape';
symbolInfo.props = {
bbox: {
left: bbox.left / 20,
top: bbox.top / 20,
right: bbox.right / 20,
bottom: bbox.bottom / 20
},
bbox: symbol.bbox,
graphics: graphics
};
symbolPromise.then(function () {
graphics.drawGraphicsData(createGraphicsData(dictionary, 0));
});
break;
case 'sound':
symbolInfo.className = 'flash.media.Sound';
symbolInfo.props = { };
break;
case 'sprite':
var frameCount = symbol.frameCount;
@ -537,7 +627,7 @@ const LoaderDefinition = (function () {
};
}
var j = frame.repeat || 1;
var j = frame.repeat;
while (j--)
timeline.push(framePromise);
@ -549,6 +639,7 @@ const LoaderDefinition = (function () {
timeline: timeline,
framesLoaded: frameCount,
frameLabels: frameLabels,
frameScripts: symbol.frameScripts,
totalFrames: frameCount
};
break;
@ -559,30 +650,16 @@ 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;
loaderInfo._swfVersion = info.swfVersion;
var bounds = info.bounds;
loaderInfo._width = (bounds.xMax - bounds.xMin) / 20;
loaderInfo._height = (bounds.yMax - bounds.yMin) / 20;
var bbox = info.bbox;
loaderInfo._width = bbox.right - bbox.left;
loaderInfo._height = bbox.bottom - bbox.top;
loaderInfo._frameRate = info.frameRate;
@ -600,37 +677,36 @@ 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;
if (loader._isAvm2Enabled) {
// HACK: bind the mouse through awful shenanigans.
var mouseClass = avm2.systemDomain.getClass("flash.ui.Mouse");
mouseClass.dynamicPrototype.$bind(stage);
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);
@ -638,6 +714,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();
},

Просмотреть файл

@ -1,4 +1,4 @@
const LoaderInfoDefinition = (function () {
var LoaderInfoDefinition = (function () {
var def = {
__class__: 'flash.display.LoaderInfo',

Просмотреть файл

@ -1,7 +1,7 @@
function MorphShape() {
DisplayObject.call(this);
}
var MorphShapeDefinition = (function () {
var def = {
__class__: 'flash.display.MorphShape',
};
MorphShape.prototype = Object.create(DisplayObject.prototype, {
__class__: describeInternalProperty('flash.display.MorphShape')
});
return def;
}).call(this);

Просмотреть файл

@ -1,4 +1,4 @@
const MovieClipDefinition = (function () {
var MovieClipDefinition = (function () {
var def = {
__class__: 'flash.display.MovieClip',
@ -16,7 +16,6 @@ const MovieClipDefinition = (function () {
this._scenes = { };
this._timeline = null;
this._totalFrames = 1;
this._scenes = { };
var s = this.symbol;
if (s) {
@ -27,27 +26,265 @@ 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);
}
},
_getAS2Object: function () {
if (!this.$as2Object) {
new AS2MovieClip().$attachNativeObject(this);
}
return this.$as2Object;
},
_insertChildAtDepth: function (instance, depth) {
var children = this._children;
var depthMap = this._depthMap;
var current = depthMap[depth];
var highestDepth = depthMap.length;
var replace = false;
var index;
if (current && current._owned) {
replace = true;
index = children.indexOf(current);
} else {
var top = null;
for (var i = +depth + 1; i < highestDepth; i++) {
var info = depthMap[i];
if (info && info._animated) {
top = info;
break;
}
}
index = top ? children.indexOf(top) : children.length;
}
children.splice(index, replace, instance);
depthMap[depth] = instance;
if (replace)
this._control.replaceChild(instance._control, current._control);
else
this._control.appendChild(instance._control);
instance._animated = true;
instance._owned = true;
instance._parent = this;
instance.dispatchEvent(new flash.events.Event("added"));
},
_constructSymbol: function(symbolId, name) {
var loader = this.loaderInfo._loader;
var symbolPromise = loader._dictionary[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) ?
avm2.systemDomain.getClass(symbolInfo.className) :
avm2.applicationDomain.getClass(symbolInfo.className);
var instance = symbolClass.createAsSymbol(symbolInfo.props);
// If we bound the instance to a name, set it.
//
// XXX: I think this always has to be a trait.
if (name)
this[Multiname.getPublicQualifiedName(name)] = instance;
// Call the constructor now that we've made the symbol instance,
// instantiated all its children, and set the display list-specific
// properties.
//
// XXX: I think we're supposed to throw if the symbol class
// constructor is not nullary.
symbolClass.instance.call(instance);
instance._markAsDirty();
instance._name = name || null;
instance.dispatchEvent(new flash.events.Event("load"));
return instance;
},
_gotoFrame: function (frameNum, scene) {
if (frameNum > this._totalFrames)
frameNum = 1;
if (frameNum > this.framesLoaded)
frameNum = this.framesLoaded;
var currentFrame = this._currentFrame;
if (frameNum === 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;
}
while (currentFrame++ < frameNum) {
var children = this._children;
var depthMap = this._depthMap;
var framePromise = this._timeline[currentFrame - 1];
var highestDepth = depthMap.length;
var displayList = framePromise.value;
var loader = this.loaderInfo._loader;
for (var depth in displayList) {
this._markAsDirty();
var cmd = displayList[depth];
var current = depthMap[depth];
if (cmd === null) {
if (current && current._owned) {
var index = children.indexOf(current);
var removed = children.splice(index, 1);
this._control.removeChild(current._control);
removed[0].dispatchEvent(new flash.events.Event("removed"));
if (depth < highestDepth)
depthMap[depth] = undefined;
else
depthMap.splice(-1);
}
} else {
var clipDepth = cmd.clipDepth;
var cxform = cmd.cxform;
var matrix = cmd.matrix;
var target;
if (cmd.symbolId) {
var name = cmd.name;
var events = cmd.hasEvents ? cmd.events : null;
var instance = this._constructSymbol(cmd.symbolId, name);
if (!loader._isAvm2Enabled) {
this._initAvm1Bindings(instance, name, events);
}
this._insertChildAtDepth(instance, depth);
if (current && current._owned) {
if (!clipDepth)
clipDepth = current._clipDepth;
if (!cxform)
cxform = current._cxform;
if (!matrix)
matrix = current._currentTransform;
}
target = instance;
} else if (current && current._animated) {
target = current;
}
if (clipDepth)
target._clipDepth = clipDepth;
if (cxform)
target._cxform = cxform;
if (matrix) {
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;
var y = target._y = matrix.ty;
target._currentTransform = matrix;
}
}
}
}
this._currentFrame = frameNum;
this._requestCallFrame();
},
_requestCallFrame: function () {
this._scriptExecutionPending = true;
this.stage._callFrameRequested = true;
},
_initAvm1Bindings: function (instance, name, events) {
var loader = this.loaderInfo._loader;
var avm1Context = loader._avm1Context;
var symbolProps = instance.symbol;
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;
instance._refreshAS2Variables = function() {
instance.text = clip[variableName];
};
}
if (events) {
var eventsBound = [];
for (var i = 0; i < events.length; i++) {
var event = events[i];
if (event.eoe) {
break;
}
var fn = function(actionBlock) {
return executeActions(actionBlock, avm1Context, this._getAS2Object());
}.bind(instance, event.actionsData);
for (var eventName in event) {
if (eventName.indexOf("on") !== 0 || !event[eventName])
continue;
var avm2EventName = eventName[2].toLowerCase() + eventName.substring(3);
this.addEventListener(avm2EventName, fn, false);
eventsBound.push({name: avm2EventName, fn: fn});
}
}
if (eventsBound.length > 0) {
instance.addEventListener('removed', function (eventsBound) {
for (var i = 0; i < eventsBound.length; i++) {
this.removeEventListener(eventsBound[i].name, eventsBound[i].fn, false);
}
}.bind(this, eventsBound), false);
}
}
if (name) {
this._getAS2Object()[name] = instance._getAS2Object();
}
},
get currentFrame() {
return this._currentFrame;
},
@ -72,142 +309,48 @@ const MovieClipDefinition = (function () {
get framesLoaded() {
return this._framesLoaded;
},
gotoFrame: function (frameNum, scene) {
if (frameNum > this._totalFrames)
frameNum = 1;
get totalFrames() {
return this._totalFrames;
},
get trackAsMenu() {
return false;
},
set trackAsMenu(val) {
notImplemented();
},
if (frameNum > this.framesLoaded)
frameNum = this.framesLoaded;
if (frameNum === this._currentFrame) {
return;
}
var children = this._children;
var depthMap = this._depthMap;
var framePromise = this._timeline[frameNum - 1];
var highestDepth = depthMap.length;
var displayList = framePromise.value;
var loader = this.loaderInfo._loader;
var newInstances = [];
for (var depth in displayList) {
var cmd = displayList[depth];
var current = depthMap[depth];
if (cmd === null) {
if (current && current._owned) {
var index = children.indexOf(current);
children.splice(index, 1);
if (depth <= highestDepth)
depthMap[depth] = undefined;
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
depthMap.splice(-1);
frameScripts[frameNum] = [fn];
}
} else {
var cxform = cmd.cxform;
var matrix = cmd.matrix;
var target;
if (cmd.symbolId) {
var index = 0;
var symbolInfo = loader.getSymbolInfoById(cmd.symbolId);
// HACK application domain may have the symbol class --
// checking which domain has a symbol class
var symbolClass = avm2.systemDomain.findClass(symbolInfo.className) ?
avm2.systemDomain.getClass(symbolInfo.className) :
avm2.applicationDomain.getClass(symbolInfo.className);
var instance = symbolClass.createAsSymbol(symbolInfo.props);
var replace = 0;
if (current && current._owned) {
if (!cxform)
cxform = current._cxform;
index = children.indexOf(current);
if (!matrix)
matrix = current.transform.matrix;
replace = 1;
} else {
var top = null;
for (var i = +depth + 1; i < highestDepth; i++) {
var info = depthMap[i];
if (info && info._animated)
top = info;
}
index = top ? children.indexOf(top) : children.length;
}
children.splice(index, replace, instance);
depthMap[depth] = instance;
target = instance;
// If we bound the instance to a name, set it.
//
// XXX: I think this always has to be a trait.
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
// properties.
//
// XXX: I think we're supposed to throw if the symbol class
// constructor is not nullary.
symbolClass.instance.call(instance);
instance._animated = true;
instance._owned = true;
instance._parent = this;
} else if (current && current._animated) {
target = current;
}
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
};
}
}
}
this._currentFrame = frameNum;
this._scriptExecutionPending = true;
},
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;
@ -229,19 +372,10 @@ const MovieClipDefinition = (function () {
},
stop: function () {
this._isPlaying = false;
},
get totalFrames() {
return this._totalFrames;
},
get trackAsMenu() {
return false;
},
set trackAsMenu(val) {
notImplemented();
}
};
const desc = Object.getOwnPropertyDescriptor;
var desc = Object.getOwnPropertyDescriptor;
def.__glue__ = {
native: {

Просмотреть файл

@ -1,4 +1,4 @@
const ShapeDefinition = (function () {
var ShapeDefinition = (function () {
var def = {
__class__: 'flash.display.Shape',

Просмотреть файл

@ -1,3 +1,131 @@
const SimpleButtonDefinition = {
__class__: 'flash.display.SimpleButton'
};
var SimpleButtonDefinition = (function () {
var def = {
__class__: 'flash.display.SimpleButton',
get downState() {
return this._downState;
},
set downState(val) {
this._downState = val;
},
get hitTestState() {
return this._hitArea;
},
set hitTestState(val) {
this._hitArea = val;
},
get overState() {
return this._overState;
},
set overState(val) {
this._overState = val;
},
get upState() {
return this._upState;
},
set upState(val) {
this._upState = val;
},
get useHandCursor() {
return this._useHandCursor;
},
set useHandCursor(val) {
this._useHandCursor = val;
},
_getAS2Object: function () {
if (!this.$as2Object) {
new AS2Button().$attachNativeObject(this);
}
return this.$as2Object;
},
initialize: function () {
this._downState = null;
this._hitArea = null;
this._isMouseDown = false;
this._isMouseOver = false;
this._mouseChildren = false;
this._overState = null;
this._upState = null;
this._useHandCursor = true;
var s = this.symbol;
if (s) {
var states = s.states;
if (states.down)
this._downState = createState(states.down.value, this);
if (states.hitTest)
this._hitArea = createState(states.hitTest.value, this);
if (states.over)
this._overState = createState(states.over.value, this);
if (states.up)
this._upState = createState(states.up.value, this);
}
// binding mouse events
var 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_OUT, function (evt) {
this._isMouseOver = 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_UP, function (evt) {
this._isMouseDown = false;
this._updateButton();
}.bind(this), true);
},
_updateButton: function () {
this._markAsDirty();
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];
},
get shouldHaveHandCursor() {
return this._useHandCursor;
}
};
function createState(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;
}
var desc = Object.getOwnPropertyDescriptor;
def.__glue__ = {
native: {
instance: {
downState: desc(def, "downState"),
hitTestState: desc(def, "hitTestState"),
overState: desc(def, "overState"),
upState: desc(def, "upState"),
useHandCursor: desc(def, "useHandCursor"),
_updateButton: def._updateButton,
}
}
};
return def;
}).call(this);

Просмотреть файл

@ -1,8 +1,10 @@
const SpriteDefinition = (function () {
var SpriteDefinition = (function () {
var def = {
__class__: 'flash.display.Sprite',
initialize: function () {
this._buttonMode = false;
this._useHandCursor = true;
var s = this.symbol;
if (s) {
this._graphics = s.graphics || new flash.display.Graphics;
@ -11,20 +13,36 @@ const SpriteDefinition = (function () {
}
},
_constructChildren: function () {
var children = this._children;
for (var i = 0, n = children.length; i < n; i++) {
var symbolPromise = children[i];
var symbolInfo = symbolPromise.value;
var symbolClass = avm2.systemDomain.findClass(symbolInfo.className) ?
avm2.systemDomain.getClass(symbolInfo.className) :
avm2.applicationDomain.getClass(symbolInfo.className);
var child = symbolClass.createAsSymbol(symbolInfo.props);
symbolClass.instance.call(child);
children[i] = child;
child._owned = false;
child._parent = this;
}
},
get buttonMode() {
return false;
return this._buttonMode;
},
set buttonMode(val) {
notImplemented();
this._buttonMode = val;
},
get graphics() {
return this._graphics;
},
get hitArea() {
return null;
return this._hitArea;
},
set hitArea(val) {
notImplemented();
this._hitArea = val;
},
get soundTransform() {
notImplemented();
@ -32,6 +50,17 @@ const SpriteDefinition = (function () {
set soundTransform(val) {
notImplemented();
},
get useHandCursor() {
return this._useHandCursor;
},
set useHandCursor(val) {
this._useHandCursor = val;
this._stage._syncCursor();
},
get shouldHaveHandCursor() {
return this._buttonMode && this._useHandCursor;
},
startDrag: function (lockCenter, bounds) {
notImplemented();
},
@ -43,19 +72,10 @@ const SpriteDefinition = (function () {
},
stopTouchDrag: function (touchPointID) {
notImplemented();
},
get useHandCursor() {
return true;
},
set useHandCursor(val) {
notImplemented();
},
constructChildren: function () {
// notImplemented();
}
};
const desc = Object.getOwnPropertyDescriptor;
var desc = Object.getOwnPropertyDescriptor;
def.__glue__ = {
native: {
@ -67,7 +87,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")
@ -77,4 +97,3 @@ const SpriteDefinition = (function () {
return def;
}).call(this);

Просмотреть файл

@ -1,4 +1,4 @@
const StageDefinition = (function () {
var StageDefinition = (function () {
var COLOR_CORRECTION_DEFAULT = 'default';
var COLOR_CORRECTION_OFF = 'on';
var COLOR_CORRECTION_ON = 'off';
@ -31,8 +31,14 @@ const StageDefinition = (function () {
initialize: function () {
this._color = 0xFFFFFFFF;
this._focus = null;
this._clickTarget = null;
this._showRedrawRegions = false;
this._stage = this;
this._stageHeight = 0;
this._stageWidth = 0;
this._transform = { };
this._mouseJustLeft = false;
},
get allowsFullScreen() {
@ -116,6 +122,7 @@ const StageDefinition = (function () {
get wmodeGPU() {
return false;
},
invalidate: function () {
notImplemented();
},
@ -124,7 +131,7 @@ const StageDefinition = (function () {
}
};
const desc = Object.getOwnPropertyDescriptor;
var desc = Object.getOwnPropertyDescriptor;
// TODO
def.__glue__ = {

Просмотреть файл

@ -1,4 +1,4 @@
const EventDefinition = (function () {
var EventDefinition = (function () {
var EVENT_PHASE_CAPTURING_PHASE = 1;
var EVENT_PHASE_AT_TARGET = 2;
var EVENT_PHASE_BUBBLING_PHASE = 3;
@ -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,13 +39,10 @@ const EventDefinition = (function () {
},
stopPropagation: function () {
notImplemented();
},
get target() {
return this._target;
},
}
};
const desc = Object.getOwnPropertyDescriptor;
var desc = Object.getOwnPropertyDescriptor;
def.__glue__ = {
script: {

Просмотреть файл

@ -1,4 +1,4 @@
const EventDispatcherDefinition = (function () {
var EventDispatcherDefinition = (function () {
var CUSTOM_DOM_EVENT_PREFIX = 'shumway.';
var def = {
@ -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();
@ -89,12 +88,14 @@ const EventDispatcherDefinition = (function () {
var handlers = useCapture ? this._captureHandlers : this._handlers;
var handler = handlers[type];
if (handler) {
var listeners = handler.listeners;
var i = listeners.indexOf(listener);
if (i > -1)
listeners.splice(i, 1);
if (!listeners.length) {
var queue = handler.queue;
for (var i = 0; i < queue.length; i++) {
if (queue[i].listener === listener) {
queue.splice(i, 1);
break;
}
}
if (!queue.length) {
if (this._control)
this._control.removeEventListener(CUSTOM_DOM_EVENT_PREFIX + type, handler, useCapture);

Просмотреть файл

@ -1,9 +1,12 @@
const KeyboardEventDefinition = (function () {
var KeyboardEventDefinition = (function () {
var def = {
__class__: 'flash.events.KeyboardEvent',
updateAfterEvent: function () {
notImplemented();
},
get keyCode() {
return this.private$flash$events$KeyboardEvent$m_keyCode;
}
};

Просмотреть файл

@ -1,4 +1,4 @@
const MouseEventDefinition = (function () {
var MouseEventDefinition = (function () {
var def = {
__class__: 'flash.events.MouseEvent',
@ -31,7 +31,7 @@ const MouseEventDefinition = (function () {
ROLL_OUT: 'public ROLL_OUT',
ROLL_OVER: 'public ROLL_OVER'
},
}
},
native: {
instance: {

Просмотреть файл

@ -0,0 +1,21 @@
var TextEventDefinition = (function () {
var def = {
__class__: 'flash.events.TextEvent'
};
def.__glue__ = {
script: {
static: {
LINK: "public LINK",
TEXT_INPUT: "public TEXT_INPUT"
}
},
native: {
instance: {
}
}
};
return def;
}).call(this);

Просмотреть файл

@ -1,4 +1,4 @@
const TimerEventDefinition = (function () {
var TimerEventDefinition = (function () {
var def = {
__class__: 'flash.events.TimerEvent',

17
src/flash/external/ExternalInterface.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,17 @@
var ExternalInterfaceDefinition = (function () {
var def = {};
function getAvailable() {
return false;
}
def.__glue__ = {
native: {
static: {
available: { get: getAvailable }
}
}
};
return def;
}).call(this);

Просмотреть файл

@ -1,4 +1,4 @@
const ColorTransformDefinition = (function () {
var ColorTransformDefinition = (function () {
var def = {
__class__: 'flash.geom.ColorTransform',

Просмотреть файл

@ -1,4 +1,4 @@
const MatrixDefinition = (function () {
var MatrixDefinition = (function () {
var def = {
__class__: 'flash.geom.Matrix',

Просмотреть файл

@ -1,4 +1,4 @@
const PointDefinition = (function () {
var PointDefinition = (function () {
var def = {
__class__: 'flash.geom.Point',

Просмотреть файл

@ -1,4 +1,4 @@
const RectangleDefinition = (function () {
var RectangleDefinition = (function () {
var def = {
__class__: 'flash.geom.Rectangle',

Просмотреть файл

@ -1,12 +1,7 @@
const TransformDefinition = (function () {
var 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,34 +46,48 @@ 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;
}
};
const desc = Object.getOwnPropertyDescriptor;
var desc = Object.getOwnPropertyDescriptor;
def.__glue__ = {
native: {

15
src/flash/media/Sound.js Normal file
Просмотреть файл

@ -0,0 +1,15 @@
var SoundDefinition = (function () {
var def = {
initialize: function initialize() {
}
};
def.__glue__ = {
native: {
instance: {
}
}
};
return def;
}).call(this);

Просмотреть файл

@ -0,0 +1,17 @@
var SoundMixerDefinition = (function () {
var def = {};
function stopAll() {
// TODO stop all sounds
}
def.__glue__ = {
native: {
static: {
stopAll: stopAll
}
}
};
return def;
}).call(this);

Просмотреть файл

@ -1,13 +1,7 @@
function SoundTransform(volume, pan) {
EventDispatcher.call(this);
var SoundTransformDefinition = (function () {
var def = {
__class__: 'flash.media.SoundTransform',
};
this.volume = volume;
this.pan = pan || 0;
}
SoundTransform.prototype = Object.create(null, {
__class__: describeInternalProperty('flash.media.SoundTransform'),
_timerDispatch: describeMethod(function () {
})
});
return def;
}).call(this);

Просмотреть файл

@ -1,4 +1,4 @@
const VideoDefinition = (function () {
var VideoDefinition = (function () {
var def = {
initialize: function initialize() {
this._element = document.createElement('video');
@ -11,6 +11,9 @@ const VideoDefinition = (function () {
this._netStream = netStream;
this._element.src = netStream._url;
},
ctor: function(width, height) {
// notImplemented();
},
draw: function (ctx) {
if (!this._added) {
ctx.canvas.parentNode.appendChild(this._element);
@ -23,7 +26,8 @@ const VideoDefinition = (function () {
def.__glue__ = {
native: {
instance: {
attachNetStream: def.attachNetStream
attachNetStream: def.attachNetStream,
ctor: def.ctor
}
}
};

Просмотреть файл

@ -1,5 +1,20 @@
const NetConnectionDefinition = (function () {
var NetConnectionDefinition = (function () {
var def = {
connect: function(command /*, ...arguments */) {
// notImplemented();
},
invokeWithArgsArray: function() {
// notImplemented();
}
};
def.__glue__ = {
native: {
instance: {
connect: def.connect,
invokeWithArgsArray: def.invokeWithArgsArray
}
}
};
return def;

Просмотреть файл

@ -1,9 +1,21 @@
const NetStreamDefinition = (function () {
var NetStreamDefinition = (function () {
var def = {
ctor: function(connection, peerID) {
// notImplemented();
},
play: function (url) {
this._url = url;
}
};
def.__glue__ = {
native: {
instance: {
ctor: def.ctor,
play: def.play
}
}
};
return def;
}).call(this);

Просмотреть файл

@ -0,0 +1,17 @@
var ResponderDefinition = (function () {
var def = {
ctor: function(result, status) {
// notImplemented();
}
};
def.__glue__ = {
native: {
instance: {
ctor: def.ctor
}
}
};
return def;
}).call(this);

Просмотреть файл

@ -0,0 +1,59 @@
var URLRequestDefinition = (function () {
var def = {
initialize: function () {
this._url = null;
this._method = 'GET';
this._data = null;
this._contentType = 'application/x-www-form-urlencoded';
},
get contentType() {
return this._contentType;
},
set contentType(val) {
this._contentType = val;
},
get data() {
return this._data;
},
set data(val) {
this._data = val;
},
get method() {
return this._method;
},
setMethod: function (val) {
this._method = val;
},
get requestHeaders() {
return this._requestHeaders;
},
setRequestHeaders: function (val) {
this._requestHeaders = val;
},
get url() {
return this._url;
},
set url(val) {
this._url= val;
},
};
var desc = Object.getOwnPropertyDescriptor;
def.__glue__ = {
native: {
instance: {
contentType: desc(def, 'contentType'),
data: desc(def, 'data'),
method: desc(def, 'method'),
requestHeaders: desc(def, 'requestHeaders'),
setMethod: def.setMethod,
setRequestHeaders: def.setRequestHeaders,
url: desc(def, 'url')
}
}
};
return def;
}).call(this);

Просмотреть файл

@ -99,10 +99,14 @@ var as3error = {};
M("flash.display.Sprite", "SpriteClass", SpriteDefinition),
M("flash.display.MovieClip", "MovieClipClass", MovieClipDefinition),
M("flash.display.Shape", "ShapeClass", ShapeDefinition),
M("flash.display.Bitmap", "BitmapClass", BitmapDefinition),
M("flash.display.BitmapData", "BitmapDataClass", BitmapDataDefinition),
M("flash.display.Stage", "StageClass", StageDefinition),
M("flash.display.Loader", "LoaderClass", LoaderDefinition),
M("flash.display.LoaderInfo", "LoaderInfoClass", LoaderInfoDefinition),
M("flash.display.Graphics", "GraphicsClass", GraphicsDefinition),
M("flash.display.SimpleButton", "SimpleButtonClass", SimpleButtonDefinition),
M("flash.display.MorphShape", "MorphShapeClass", MorphShapeDefinition),
M("flash.geom.Point", "PointClass", PointDefinition),
M("flash.geom.Rectangle", "RectangleClass", RectangleDefinition),
@ -113,14 +117,31 @@ 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.TextEvent", "TextEventClass", TextEventDefinition),
M("flash.events.TimerEvent", "TimerEventClass", TimerEventDefinition),
M("flash.ui.Keyboard", "KeyboardClass", KeyboardDefinition),
M("flash.external.ExternalInterface", "ExternalInterfaceClass", ExternalInterfaceDefinition),
M("flash.ui.Keyboard", "KeyboardClass", KeyboardDefinition),
M("flash.ui.Mouse", "MouseClass", MouseDefinition),
M("flash.text.Font", "FontClass", FontDefinition),
M("flash.text.TextField", "TextFieldClass", TextFieldDefinition),
M("flash.text.StaticText", "StaticTextClass", StaticTextDefinition),
M("flash.text.Video", "VideoClass", VideoDefinition),
M("flash.media.Sound", "SoundClass", SoundDefinition),
M("flash.media.SoundMixer", "SoundMixerClass", SoundMixerDefinition),
M("flash.media.SoundTransform", "SoundTransformClass", SoundTransformDefinition),
M("flash.media.Video", "VideoClass", VideoDefinition),
M("flash.net.NetConnection", "NetConnectionClass", NetConnectionDefinition),
M("flash.net.NetStream", "NetStreamClass", NetStreamDefinition),
M("flash.net.Responder", "ResponderClass", ResponderDefinition),
M("flash.net.URLRequest", "URLRequestClass", URLRequestDefinition),
M("flash.system.FSCommand", "FSCommandClass", FSCommandDefinition),
M("flash.system.Capabilities", "CapabilitiesClass", CapabilitiesDefinition),
M("flash.utils.Timer", "TimerClass", TimerDefinition)].forEach(function (m) {
var path = m.className.split(".");
@ -136,10 +157,7 @@ var as3error = {};
// Hook up the native.
natives[m.nativeName] = function (runtime, scope, instance, baseClass) {
var c = new runtime.domain.system.Class(name, function () {
this.class.initializeInstance(this);
instance.apply(this, arguments);
});
var c = new runtime.domain.system.Class(name, instance);
c.extend(baseClass);
c.link(m.definition);
return c;
@ -153,3 +171,19 @@ natives['FlashUtilScript::getTimer'] = function GetTimerMethod(runtime, scope, i
return Date.now() - start;
};
};
natives['FlashNetScript::navigateToURL'] = function GetNavigateToURLMethod(runtime, scope, instance, baseClass) {
return function navigateToURL(request, window) {
if (!request || !request.url)
throw new Error('Invalid request object');
var url = request.url;
if (/^fscommand:/i.test(url)) {
var fscommand = avm2.applicationDomain.getProperty(
Multiname.fromSimpleName('flash.system.fscommand'), true, true);
fscommand.call(null, url.substring('fscommand:'.length), window);
return;
}
// TODO handle other methods than GET
window.open(url, window);
};
};

Просмотреть файл

@ -0,0 +1,18 @@
var CapabilitiesDefinition = (function () {
var def = {};
def.__glue__ = {
native: {
static: {
version: {
get: function version() {
return 'SHUMWAY 10,0,0,0';
},
enumerable: true
}
}
}
};
return def;
}).call(this);

Просмотреть файл

@ -0,0 +1,18 @@
var FSCommandDefinition = (function () {
var def = {};
function fscommand(command, parameters) {
// TODO ignoring all fscommand
console.log('FSCommand: ' + command + '; ' + parameters);
}
def.__glue__ = {
native: {
static: {
_fscommand: fscommand
}
}
};
return def;
}).call(this);

Просмотреть файл

@ -1,3 +1,52 @@
const FontDefinition = {
__class__: 'flash.text.Font'
};
var FontDefinition = (function () {
var def = {
__class__: 'flash.text.Font',
initialize: function () {
var s = this.symbol;
if (s) {
this._fontName = s.name || null;
}
},
get fontName() {
return this._fontName;
},
get fontStyle() {
return this._fontStyle;
},
get fontType() {
return this._fontType;
},
hasGlyphs: function hasGlyphs(str) {
return true; // TODO
},
};
function enumerateFonts() {
return []; // TODO
}
function registerFont(font) {
throw 'Not implemented: registerFont';
}
var desc = Object.getOwnPropertyDescriptor;
def.__glue__ = {
native: {
instance: {
fontName: desc(def, "fontName"),
fontStyle: desc(def, "fontStyle"),
fontType: desc(def, "fontType"),
hasGlyphs: def.hasGlyphs
},
static: {
enumerateFonts: enumerateFonts,
registerFont: registerFont
}
}
};
return def;
}).call(this);

Просмотреть файл

@ -1,4 +1,4 @@
const StaticTextDefinition = (function () {
var StaticTextDefinition = (function () {
var def = {
__class__: 'flash.text.StaticText',
@ -17,7 +17,7 @@ const StaticTextDefinition = (function () {
}
};
const desc = Object.getOwnPropertyDescriptor;
var desc = Object.getOwnPropertyDescriptor;
def.__glue__ = {
native: {

Просмотреть файл

@ -1,4 +1,4 @@
const TextFieldDefinition = (function () {
var TextFieldDefinition = (function () {
var def = {
__class__: 'flash.text.TextField',
@ -10,15 +10,25 @@ const TextFieldDefinition = (function () {
}
},
_getAS2Object: function () {
if (!this.$as2Object) {
new AS2TextField().$attachNativeObject(this);
}
return this.$as2Object;
},
get text() {
return this._text;
},
set text(val) {
if (this._text !== val) {
this._text = val;
this._markAsDirty();
}
}
};
const desc = Object.getOwnPropertyDescriptor;
var desc = Object.getOwnPropertyDescriptor;
def.__glue__ = {
native: {

Просмотреть файл

@ -1,11 +1,8 @@
var ShumwayKeyboardListener = {
handleEvent: function (domEvt) {
// XXX: Use strings directly if KEY_UP/KEY_DOWN and class lookup is too
// slow.
var KEClass = avm2.systemDomain.getClass("flash.events.KeyboardEvent");
if (this.focus) {
this.focus.dispatchEvent(new flash.events.KeyboardEvent(
domEvt.type === 'keyup' ? KEClass.KEY_UP : KEClass.KEY_DOWN,
domEvt.type === 'keyup' ? 'keyUp' : 'keyDown',
true,
false,
domEvt.charCode,
@ -22,7 +19,7 @@ var ShumwayKeyboardListener = {
window.addEventListener('keydown', ShumwayKeyboardListener);
window.addEventListener('keyup', ShumwayKeyboardListener);
const KeyboardDefinition = (function () {
var KeyboardDefinition = (function () {
var def = {
get capsLock() {
return false; // TODO Stage.instance.$keyboard.capsLock;
@ -41,7 +38,7 @@ const KeyboardDefinition = (function () {
}
};
const desc = Object.getOwnPropertyDescriptor;
var desc = Object.getOwnPropertyDescriptor;
def.__glue__ = {
script: {

Просмотреть файл

@ -1,29 +1,51 @@
var Mouse = describePrototype({
cursor: describeAccessor(
function () {
return 'auto'; // TODO
var MouseDefinition = (function() {
var def = {
__class__: 'flash.ui.Mouse',
$bind: function(stage) {
this._stage = stage;
},
function (val) {
};
function hide() {
this._stage._setCursorVisible(false);
}
function show() {
this._stage._setCursorVisible(true);
}
function registerCursor() {
notImplemented();
}
),
supportsCursor: describeAccessor(function () {
return true; // TODO
}),
supportsNativeCursor: describeAccessor(function () {
return true; // TODO
}),
hide: describeMethod(function () {
function unregisterCursor() {
notImplemented();
}),
registerCursor: describeMethod(function (name, cursor) {
notImplemented();
}),
show: describeMethod(function () {
notImplemented();
}),
unregisterCursor: describeMethod(function (name) {
notImplemented();
})
});
}
def.__glue__ = {
native: {
static: {
cursor: {
get: function () { return 'auto'; }, //TODO
set: function () { notImplemented(); }
},
supportsCursor: {
get: function () { return true; } // TODO
},
supportsNativeCursor: {
get: function () { return true; } // TODO
},
hide: hide,
show: show,
registerCursor: registerCursor,
unregisterCursor: unregisterCursor
},
},
};
return def;
}).call(this);

Просмотреть файл

@ -1,28 +1,3 @@
function describePrototype() {
if (arguments.length === 1) {
return Object.create(Object.prototype, arguments[0]);
}
return Object.create(arguments[0], arguments[1]);
}
function describeAccessor(get, set) {
return { get: get, set: set, configurable: true, enumerable: true };
}
function describeConst(val) {
return { value: val, configurable: true, enumerable: true };
}
function describeInternalProperty(val) {
return { value: val, writable: true };
}
function describeLazyProperty(name, getter) {
return describeAccessor(function () {
var val = getter.call(this);
Object.defineProperty(this, name, describeProperty(val));
return val;
});
}
function describeMethod(fn) {
return describeProperty(fn);
}
function describeProperty(val) {
return { value: val, writable: true, configurable: true, enumerable: true };
}
@ -45,7 +20,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);

Просмотреть файл

@ -1,4 +1,4 @@
const TimerDefinition = (function () {
var TimerDefinition = (function () {
var def = {
__class__: 'flash.utils.Timer',
initialize: function () {

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- mode: javascript; tab-width: 4; insert-tabs-mode: nil; indent-tabs-mode: nil -*- */
/* -*- mode: javascript; tab-width: 4; indent-tabs-mode: nil -*- */
/** @const */ var FORMAT_COLORMAPPED = 3;
/** @const */ var FORMAT_15BPP = 4;
@ -12,13 +12,13 @@ function rgbToString(bytes, pos) {
return fromCharCode(red, green, blue);
}
function argbToString(bytes, pos) {
var alpha = bytes[pos];
var alpha = bytes[pos] / 0xff;
if (!alpha)
return '\x00\x00\x00\x00';
// RGB values are alpha pre-multiplied (per SWF spec).
var red = 0 | ((bytes[pos + 1] * 255) / alpha);
var green = 0 | ((bytes[pos + 2] * 255) / alpha);
var blue = 0 | ((bytes[pos + 3] * 255) / alpha);
var red = 0 | (bytes[pos + 1] / alpha);
var green = 0 | (bytes[pos + 2] / alpha);
var blue = 0 | (bytes[pos + 3] / alpha);
return fromCharCode(red, green, blue, alpha);
}
@ -161,6 +161,8 @@ function defineBitmap(tag) {
return {
type: 'image',
id: tag.id,
width: width,
height: height,
mimeType: 'image/png',
data: data
};

Просмотреть файл

@ -1,13 +1,12 @@
/* -*- mode: javascript; tab-width: 4; insert-tabs-mode: nil; indent-tabs-mode: nil -*- */
/* -*- mode: javascript; tab-width: 4; indent-tabs-mode: nil -*- */
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;
}

Просмотреть файл

@ -5,12 +5,32 @@ SWF.embed = function(file, container, options) {
var loaderInfo = loader.contentLoaderInfo;
var stage = new flash.display.Stage;
// HACK support of HiDPI displays
var pixelRatio = 'devicePixelRatio' in window ? window.devicePixelRatio : 1;
var canvasHolder = null;
if (pixelRatio > 1) {
var cssScale = 'scale(' + (1/pixelRatio) + ', ' + (1/pixelRatio) + ')';
canvas.setAttribute('style', '-moz-transform: ' + cssScale + ';' +
'-webkit-transform: ' + cssScale + ';' +
'transform: ' + cssScale + ';' +
'-moz-transform-origin: 0% 0%;' +
'-webkit-transform-origin: 0% 0%;' +
'transform-origin: 0% 0%;');
canvasHolder = document.createElement('div');
canvasHolder.setAttribute('style', 'display: inline-block; overflow: hidden;');
canvasHolder.appendChild(canvas);
}
loader._stage = stage;
stage._loader = loader;
function fitCanvas(container, canvas) {
canvas.width = container.clientWidth;
canvas.height = container.clientHeight;
if (canvasHolder) {
canvasHolder.style.width = container.clientWidth + 'px';
canvasHolder.style.height = container.clientHeight + 'px';
}
canvas.width = container.clientWidth * pixelRatio;
canvas.height = container.clientHeight * pixelRatio;
}
loaderInfo.addEventListener('init', function () {
@ -25,27 +45,88 @@ SWF.embed = function(file, container, options) {
fitCanvas.bind(container, canvas);
});
} else {
canvas.width = stage._stageWidth;
canvas.height = stage._stageHeight;
if (canvasHolder) {
canvasHolder.style.width = stage._stageWidth + 'px';
canvasHolder.style.height = stage._stageHeight + 'px';
}
canvas.width = stage._stageWidth * pixelRatio;
canvas.height = stage._stageHeight * pixelRatio;
}
container.setAttribute("style", "position: relative");
canvas.addEventListener('click', function () {
ShumwayKeyboardListener.focus = stage;
if (stage._clickTarget)
stage._clickTarget.dispatchEvent(new flash.events.MouseEvent('click'));
});
canvas.addEventListener('dblclick', function () {
if (stage._clickTarget && stage._clickTarget._doubleClickEnabled)
stage._clickTarget.dispatchEvent(new flash.events.MouseEvent('doubleClick'));
});
canvas.addEventListener('mousedown', function () {
if (stage._clickTarget)
stage._clickTarget.dispatchEvent(new flash.events.MouseEvent('mouseDown'));
});
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;
});
canvas.addEventListener('mouseup', function () {
if (stage._clickTarget)
stage._clickTarget.dispatchEvent(new flash.events.MouseEvent('mouseUp'));
});
canvas.addEventListener('mouseover', function () {
stage._mouseOver = true;
});
canvas.removeEventListener('mouseout', function () {
stage._mouseOver = false;
stage._mouseJustLeft = true;
});
var bgcolor = loaderInfo._backgroundColor;
stage._color = bgcolor;
canvas.style.background = toStringRgba(bgcolor);
stage._children[0] = loader._content;
container.appendChild(canvas);
renderStage(stage, ctx);
var root = loader._content;
stage._children[0] = root;
stage._control.appendChild(root._control);
var cursorVisible = true;
function syncCursor() {
var newCursor;
if (cursorVisible) {
if (stage._clickTarget && stage._clickTarget.shouldHaveHandCursor)
newCursor = 'pointer';
else
newCursor = 'auto';
} else {
newCursor = 'none';
}
container.style.cursor = newCursor;
}
stage._setCursorVisible = function(val) {
cursorVisible = val;
syncCursor();
};
stage._syncCursor = syncCursor;
syncCursor();
container.appendChild(canvasHolder || canvas);
renderStage(stage, ctx, options.onFrame);
});
if (options.onComplete) {
@ -54,5 +135,5 @@ SWF.embed = function(file, container, options) {
});
}
loader.loadFrom(file);
loader._loadFrom(file);
};

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- mode: javascript; tab-width: 4; insert-tabs-mode: nil; indent-tabs-mode: nil -*- */
/* -*- mode: javascript; tab-width: 4; indent-tabs-mode: nil -*- */
var nextFontId = 1;
@ -18,6 +18,9 @@ function defineFont(tag, dictionary) {
var glyphIndex = { };
var ranges = [];
var glyphs = tag.glyphs;
var glyphCount = glyphs.length;
if (tag.codes) {
codes = codes.concat(tag.codes);
for (var i = 0, code; code = codes[i]; ++i)
@ -39,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;
@ -130,7 +135,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 +286,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

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- mode: javascript; tab-width: 4; insert-tabs-mode: nil; indent-tabs-mode: nil -*- */
/* -*- mode: javascript; tab-width: 4; indent-tabs-mode: nil -*- */
var defaultTemplateSet = [
readSi8, readSi16, readSi32, readUi8, readUi16, readUi32, readFixed,

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- mode: javascript; tab-width: 4; insert-tabs-mode: nil; indent-tabs-mode: nil -*- */
/* -*- mode: javascript; tab-width: 4; indent-tabs-mode: nil -*- */
var plte = createPngChunk('PLTE', (new Array(769)).join('\x00'));
var alphaValues = [];
@ -18,7 +18,7 @@ function defineImage(tag, dictionary) {
if (tag.mimeType === 'image/jpeg') {
var width = 0;
var height = 0;
var i = 2;
var i = 0;
var n = imgData.length;
var code;
do {
@ -103,7 +103,7 @@ function defineImage(tag, dictionary) {
var header = tables.data;
data = header.substr(0, header.length - 2) + data;
} else {
data = '\xff\xd8' + data;
data = data;
}
} else {
var numChunks = imgData.length / 65536;
@ -118,6 +118,8 @@ function defineImage(tag, dictionary) {
var img = {
type: 'image',
id: tag.id,
width: width,
height: height,
mimeType: tag.mimeType,
data: data
};

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- mode: javascript; tab-width: 4; insert-tabs-mode: nil; indent-tabs-mode: nil -*- */
/* -*- mode: javascript; tab-width: 4; indent-tabs-mode: nil -*- */
var codeLengthOrder = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- mode: javascript; tab-width: 4; insert-tabs-mode: nil; indent-tabs-mode: nil -*- */
/* -*- mode: javascript; tab-width: 4; indent-tabs-mode: nil -*- */
function defineLabel(tag, dictionary) {
var records = tag.records;
@ -42,16 +42,10 @@ function defineLabel(tag, dictionary) {
}
}
cmds.push('c.restore()');
var bounds = tag.bounds;
var label = {
type: 'label',
id: tag.id,
bbox: {
left: bounds.xMin,
top: bounds.xMax,
right: bounds.yMin,
bottom: bounds.yMax
},
bbox: tag.bbox,
data: cmds.join('\n')
};
if (dependencies.length)

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- mode: javascript; tab-width: 4; insert-tabs-mode: nil; indent-tabs-mode: nil -*- */
/* -*- mode: javascript; tab-width: 4; indent-tabs-mode: nil -*- */
var tagHandler = {
/* End */ 0: undefined,

700
src/swf/prototypes.js поставляемый
Просмотреть файл

@ -1,700 +0,0 @@
/* -*- mode: javascript; tab-width: 4; insert-tabs-mode: nil; indent-tabs-mode: nil -*- */
//var identityMatrix = {
// scaleX: 1,
// scaleY: 1,
// skew0: 0,
// skew1: 0,
// translateX: 0,
// translateY: 0
//};
//
//function DisplayListItem(character) {
// this.character = character;
//}
//function TimelineLoader(totalFrames, pframes, dictionary) {
// var currentPframe = 0;
// var ptimeline = [];
// var frameLabels = {};
// var framesLoaded = 0;
//
// var ptimelinePromises = [];
// for (var i = 0; i < totalFrames; i++)
// ptimelinePromises.push(new Promise);
//
// function prefetchFrame() {
// var prefetchPortion = 20, prefetchInterval = 100;
// setTimeout(function() {
// ensureFrame(Math.min(ptimeline.length + prefetchPortion, totalFrames));
// }, prefetchInterval);
// }
//
// var loader = this;
// var lastFramePromise = Promise.resolved, lastFrame = null;
// function ensureFrame(frameNum) {
// var n = ptimeline.length;
// while (n < frameNum) {
// var frame = create(lastFrame);
// lastFrame = frame;
// var pframe = pframes[currentPframe++];
// if (!pframe)
// break;
// var currentFrame = n + 1;
// if (pframe.labelName)
// frameLabels[pframe.labelName.toLowerCase()] = currentFrame;
// var i = pframe.repeat || 1;
// while (i--) {
// ptimeline.push(frame);
// ++n;
// }
//
// function initCharacter(proto, entry, initObj, parent, as2Context) {
// var character;
// var matrix = entry.matrix || initObj.matrix || identityMatrix;
// var cxform = entry.cxform || initObj.cxform;
// var ratio = (entry.ratio || 0) / 0xffff;
//
// if (proto instanceof DisplayListItem)
// character = proto.character; // reusing created one
// else {
// // creates new instance of the character
// if (typeof proto === 'function')
// character = new proto(as2Context);
// else if (proto.constructor !== Object)
// character = proto.constructor(as2Context);
// else
// character = create(proto);
//
// character.matrix = matrix;
// character.cxform = cxform;
// if (character.draw)
// character.ratio = ratio;
//
// if (entry.events)
// character.events = entry.events;
// if (entry.name) {
// character.name = entry.name;
// parent.$addChild(entry.name, character);
// }
// character._parent = parent;
// character._root = parent.root || parent;
// if (character.variableName)
// parent.$bindVariable(character);
// }
//
// var item = new DisplayListItem(character);
// item.matrix = matrix;
// item.cxform = cxform;
// if (character.draw)
// item.ratio = ratio;
//
// return item;
// }
//
// function buildFromPrototype(proto, entry, obj, frame, depth, promise) {
// var objectCreator = (function objectCreator(parent, objectCache, asContext) {
// var character = initCharacter(objectCache.get(proto) || proto, entry,
// objectCache.get(obj) || obj, parent, asContext);
// objectCache.set(objectCreator, character);
// return character;
// });
// frame[depth] = objectCreator;
// if (promise)
// promise.resolve(objectCreator);
// }
//
// var framePromises = [lastFramePromise];
//
// var depths = keys(pframe), depth;
// while (depth = depths[0]) {
// if (+depth) {
// var entry = pframe[depth];
// if (entry) {
// var promise = null;
// var initObj = (entry.move ? frame[depth] : null) || {};
// var id = entry.symbolId;
// if (id) {
// assert(id in dictionary, 'unknown object', 'place');
// var protoPromise = dictionary.getPromise(id);
// promise = new Promise();
// frame[depth] = promise;
// protoPromise.then((function(frame, depth, entry, initObj, promise, proto) {
// if (initObj instanceof Promise) {
// initObj.then(function(obj) {
// buildFromPrototype(proto, entry, obj, frame, depth, promise);
// });
// } else {
// buildFromPrototype(proto, entry, initObj, frame, depth, promise);
// }
// }).bind(null, frame, depth, entry, initObj, promise));
// } else {
// if (initObj instanceof Promise) {
// promise = new Promise();
// frame[depth] = promise;
// initObj.then((function(frame, depth, promise, obj) {
// buildFromPrototype(obj, entry, obj, frame, depth, promise);
// }).bind(null, frame, depth, promise));
// } else {
// buildFromPrototype(initObj, entry, initObj, frame, depth, null);
// }
// }
// if (promise)
// framePromises.push(promise);
// } else {
// frame[depth] = null;
// }
// }
// depths.shift();
// }
// var framePromise = Promise.all(framePromises);
// lastFramePromise = framePromise;
// framePromise.then((function(pframe, frame, currentFrame, lastInserted) {
// function initialize(instance) {
// if (pframe.actionsData && pframe.actionsData.length > 0) {
// for (var i = 0; i < pframe.actionsData.length; i++)
// instance.addFrameScript(currentFrame - 1,
// instance.$createAS2Script(pframe.actionsData[i]));
// }
//
// if (pframe.initActionsData) {
// for (var spriteId in pframe.initActionsData) {
// instance.$createAS2Script(pframe.initActionsData[spriteId]).call(instance);
// }
// }
// if (pframe.exports) {
// instance.$addChild('soundmc', new SoundMock(pframe.exports));
// }
// if (currentFrame == 1)
// instance.$dispatchEvent('onLoad');
// }
//
// ptimelinePromises[framesLoaded].resolve(frame, ptimeline[framesLoaded - 1], initialize);
// framesLoaded++;
// while(framesLoaded < lastInserted) {
// ptimelinePromises[framesLoaded].resolve(null, frame);
// framesLoaded++;
// }
// loader.framesLoaded = framesLoaded;
// }).bind(null, pframe, frame, currentFrame, n));
// }
// if (n < totalFrames) {
// lastFramePromise.then(function() {
// prefetchFrame();
// });
// }
// }
//
// function prepareTimeline(instance, as2Context) {
// // instance shall implement the following methods:
// // $setDisplayList, $createAS2Script, $addChild, $dispatchEvent, $addFrameScript
// var previousDisplayList = null;
// var objectCache = new WeakMap();
// for (var i = 0; i < totalFrames; i++) {
// ptimelinePromises[i].then((function(i, frame, previousFrame, initialize) {
// if (!frame) {
// // repeat of the previous frame
// instance.$setDisplayList(i + 1, previousDisplayList);
// return;
// }
// var displayList = [];
// for (var depth in frame) {
// if (previousFrame && previousFrame[depth] === frame[depth]) {
// displayList[depth] = previousDisplayList[depth];
// continue;
// }
// var creator = frame[depth];
// if (typeof creator === 'function')
// displayList[depth] = creator(this, objectCache, as2Context);
// else
// displayList[depth] = creator;
// }
// initialize(this);
// instance.$setDisplayList(i + 1, displayList);
// previousDisplayList = displayList;
// }).bind(instance, i));
// }
// }
//
// this.totalFrames = totalFrames;
// this.framesLoaded = 0;
// this.ptimelinePromises = ptimelinePromises;
// this.frameLabels = frameLabels;
// this.ensureFrame = ensureFrame;
// this.prepareTimeline = prepareTimeline;
//}
function MovieClipClass() {
var timeline = [];
var children = {};
var instance = this;
var as2Context = this._as2Context;
function createAS2Script(data) {
return (function() {
var as2Object = this.$as2Object;
try {
executeActions(data, as2Context, as2Object);
} catch (e) {
console.log('Error during ActionScript execution: ' + e);
}
});
}
function dispatchEvent(eventName, args) {
var as2Object = instance.$as2Object;
if (as2Object && as2Object[eventName])
as2Object[eventName].apply(as2Object, args);
if (instance.events) {
for (var i = 0; i < instance.events.length; ++i) {
var event = instance.events[i];
if (!event[eventName])
continue;
var actions = event.actionsData;
if (typeof actions !== 'function')
event.actionsData = actions = createAS2Script(actions);
actions.call(instance);
}
}
}
var as2Object;
var lastMouseCoordinates = null;
function getMouseCoordinates() {
if (lastMouseCoordinates)
return lastMouseCoordinates;
lastMouseCoordinates = { x: AS2Mouse.$lastX, y: AS2Mouse.$lastY };
instance.globalToLocal(lastMouseCoordinates);
return lastMouseCoordinates;
}
this.renderNextFrame = function(context) {
if (this.isPlaying())
this.gotoFrame((this._currentFrame % this._totalFrames) + 1);
var frameIndex = this._currentFrame - 1;
var displayList = timeline[frameIndex];
if (!displayList)
return; // skiping non-prepared frame
render(displayList, context);
}
this.$dispatchEvent = dispatchEvent;
this.$createAS2Script = createAS2Script;
this.$addChild = function(name, child) {
children[name] = child;
};
this.$setDisplayList = function(frameNum, displayList) {
timeline[frameNum - 1] = displayList;
};
this.$getDisplayList = function(frameNum) {
return timeline[frameNum - 1];
};
defineObjectProperties(this, {
$as2Object: {
get: function() {
if (!as2Object) {
var nativeObjectContructor = this.nativeObjectContructor || AS2MovieClip;
as2Object = new nativeObjectContructor();
as2Object.$attachNativeObject(this);
as2Object['this'] = as2Object;
var registerChild = (function(name, obj) {
Object.defineProperty(as2Object, name, {
get: function() {
return obj.$as2Object;
},
configurable: true,
enumerable: true
});
});
for (var child in children) {
registerChild(child, children[child]);
}
var oldAddChild = this.$addChild;
this.$addChild = (function(name, child) {
oldAddChild.call(this, name, child);
registerChild(name, child);
});
}
return as2Object;
},
enumerable: false
},
$parent: {
get: function get$parent() {
return this.parent.$as2Object;
},
enumerable: false
},
$lookupChild: {
value: function(name) {
var i = name.indexOf('/');
if (i == 0) {
if (this.parent) {
// moving to _root
var mc = this;
while (mc.parent)
mc = mc.parent;
return mc.$lookupChild(name.substring(1));
}
// already a root
name = name.substring(1);
i = name.indexOf('/');
}
var childName = i > 0 ? name.substring(0, i) : name;
var child = this;
if (childName == '..') {
if (!this.parent)
throw 'mc is _root';
child = this.parent;
} else if (childName) {
if (!(childName in children))
throw 'Child mc is not found: ' + childName;
child = children[childName];
}
return i < 0 ? child.$as2Object : child.$lookupChild(name.substring(i + 1));
},
enumerable: false
},
$bindVariable: {
value: function bindVariable(character) {
var clip;
var variableName = character.variableName;
var i = variableName.lastIndexOf('.');
if (i >= 0) {
var targetPath = variableName.substring(0, i);
targetPath = targetPath == '_root' ? '/' :
targetPath.replace('_root', '').replace('.', '/');
clip = this.$lookupChild(targetPath);
variableName = variableName.substring(i + 1);
} else
clip = instance.$as2Object;
if (!(variableName in clip))
clip[variableName] = character.value;
delete character.value;
Object.defineProperty(character, 'value', {
get: function () {
return clip[variableName];
},
enumerable: true
});
},
enumerable: false
},
getBounds: {
value: function getBounds(bounds) {
// TODO move the getBounds into utility/core classes
var frame = timeline[this._currentFrame - 1];
var rect = new Rectangle;
for (var i in frame) {
var character = frame[i].character;
rect = rect.union(character.getBounds(this));
}
//if (!bounds || bounds === this)
return rect;
//var pt1 = bounds.globalToLocal(
// this.localToGlobal({x: xMin, y: yMin}));
//var pt2 = bounds.globalToLocal(
// this.localToGlobal({x: xMax, y: yMin}));
//var pt3 = bounds.globalToLocal(
// this.localToGlobal({x: xMax, y: yMax}));
//var pt4 = bounds.globalToLocal(
// this.localToGlobal({x: xMin, y: yMax}));
//
//return {
// xMin: Math.min(pt1.x, pt2.x, pt3.x, pt4.x),
// yMin: Math.min(pt1.y, pt2.y, pt3.y, pt4.y),
// xMax: Math.max(pt1.x, pt2.x, pt3.x, pt4.x),
// yMax: Math.max(pt1.y, pt2.y, pt3.y, pt4.y)
//};
},
enumerable: false
},
localToGlobal: {
value: function localToGlobal(pt) {
var m = this.matrix;
if (this.rotation) {
var rotationCos = Math.cos(this.rotation * Math.PI / 180);
var rotationSin = Math.sin(this.rotation * Math.PI / 180);
pt = {
x: rotationCos * pt.x - rotationSin * pt.y,
y: rotationSin * pt.x + rotationCos * pt.y
};
}
var result = !m ? pt : {
x: m.a * pt.x + m.b * pt.y + m.e / 20,
y: m.c * pt.x + m.d * pt.y + m.f / 20
};
return this.parent ? this.parent.localToGlobal(result) : result;
},
enumerable: false
},
globalToLocal: {
value: function globalToLocal(pt) {
var result = this.parent ? this.parent.globalToLocal(pt) : pt;
var m = this.matrix;
var k = m ? 1 / (m.a * m.d - m.b * m.c) : 0;
var result = !m ? result : {
x: m.a * k * result.x - m.b * k * result.y +
(m.e * m.b - m.e * m.a) * k / 20,
y: -m.c * k * result.x + m.d * k * result.y +
(m.f * m.c - m.f * m.d) * k / 20
};
if (this.rotation) {
var rotationCos = Math.cos(this.rotation * Math.PI / 180);
var rotationSin = Math.sin(this.rotation * Math.PI / 180);
result = {
x: rotationCos * result.x + rotationSin * result.y,
y: -rotationSin * result.x + rotationCos * result.y
};
}
return result;
},
enumerable: false
},
hitTest: {
value: function hitTest() {
var bounds = this.getBounds(this.root);
if (typeof arguments[0] === 'object') {
var target = arguments[0];
var targetBounds = target.getBounds(this.root);
var x1 = this.x;
var y1 = this.y;
var x2 = target.x;
var y2 = target.y;
var x3 = Math.max(x1, x2);
var y3 = Math.max(y1, y2);
var width = Math.min(
x1 + (bounds.xMax - bounds.xMin) / 20,
x2 + (targetBounds.xMax - targetBounds.xMin) / 20
) - x3;
var height = Math.min(
y1 + (bounds.yMax - bounds.yMin) / 20,
y2 + (targetBounds.yMax - targetBounds.yMin) / 20
) - y3;
return width > 0 && height > 0;
} else {
var x = arguments[0];
var y = arguments[1];
var shapeFlag = arguments[2];
if (shapeFlag) {
// HACK shadow canvas hit testing
if (!this.hitTestCache) {
this.hitTestCache = {};
renderShadowCanvas(this);
}
var pt = this.globalToLocal({x: x, y: y});
return this.hitTestCache.isPixelPainted(pt.x, pt.y);
} else {
return x > bounds.xMin / 20 && x < bounds.xMax / 20 &&
y > bounds.yMin / 20 && y < bounds.yMax / 20;
}
}
},
enumerable: false
},
x: {
get: function get$x() {
return this.matrix.e / 20;
},
set: function set$x(value) {
if (!this.matrix)
debugger;
this.matrix.e = ~~(value * 20);
this.$fixMatrix = true;
},
enumerable: true
},
y: {
get: function get$y() {
return this.matrix.f / 20;
},
set: function set$y(value) {
this.matrix.f = ~~(value * 20);
this.$fixMatrix = true;
},
enumerable: true
},
mouseX: {
get: function get$mouseY() {
return getMouseCoordinates().x;
},
enumerable: true
},
mouseY: {
get: function get$mouseY() {
return getMouseCoordinates().y;
},
enumerable: true
}
});
var events = {
onMouseDown: function() {
lastMouseCoordinates = null;
dispatchEvent('onMouseDown');
},
onMouseMove: function() {
lastMouseCoordinates = null;
dispatchEvent('onMouseMove');
},
onMouseUp: function () {
lastMouseCoordinates = null;
dispatchEvent('onMouseUp');
},
onMouseWheel: function () {
dispatchEvent('onMouseWheel', arguments);
},
onKeyDown: function() {
dispatchEvent('onKeyDown');
},
onKeyUp: function() {
dispatchEvent('onKeyUp');
},
};
AS2Mouse.addListener(events);
AS2Key.addListener(events);
};
// HACK button as movieclip
var ButtonPrototype = function(obj, timelineLoader) {
var instance;
var AS2ButtonConditions = [
[null, 'idleToOverUp', 'idleToOverDown', null],
['overUpToIdle', null, 'overUpToOverDown', null],
['overDownToIdle', 'overDownToOverUp', null, 'overDownToOutDown'],
['outDownToIdle', null, 'outDownToOverDown', null]
];
function ButtonEvents(instance) {
this.instance = instance;
this.buttonPressed = false;
this.inBounds = false;
this.lastState = 0;
}
ButtonEvents.prototype = {
onMouseDown: function() {
this.buttonPressed = true;
this.updateButtonState();
},
onMouseMove: function() {
this.inBounds = this.instance.hitTest(this.instance.mouseX, this.instance.mouseY, true);
this.updateButtonState();
},
onMouseUp: function () {
this.buttonPressed = false;
this.updateButtonState();
},
updateButtonState: function() {
var state = 0, lastState = this.lastState;
if (!this.inBounds)
state = 0;
else if (!this.buttonPressed)
state = 1;
else
state = 2;
switch (state) {
case 0:
this.instance.gotoAndStop(1);
break;
case 1:
this.instance.gotoAndStop(2);
break;
case 2:
this.instance.gotoAndStop(3);
break;
}
if (lastState == 0 && state != 0)
this.instance.$dispatchEvent('onRollOver');
else if (lastState != 0 && state == 0)
this.instance.$dispatchEvent('onRollOut');
else if (lastState != 2 && state == 2)
this.instance.$dispatchEvent('onPress');
else if (lastState == 2 && state != 2)
this.instance.$dispatchEvent('onRelease');
this.dispatchAS2Events(lastState, state);
this.lastState = state;
},
dispatchAS2Events: function(lastState, state) {
var buttonActions = this.instance.buttonActions;
if (!buttonActions)
return;
var buttonCondition = AS2ButtonConditions[lastState][state];
if (!buttonCondition)
return;
if (!this.as2ActionsCache)
this.as2ActionsCache = {};
var buttonActionsCache = this.as2ActionsCache[buttonCondition];
if (!buttonActionsCache) {
buttonActionsCache = [];
for (var i = 0; i < buttonActions.length; i++) {
if (!buttonActions[i][buttonCondition])
continue;
var actionsData = buttonActions[i].actionsData;
buttonActionsCache.push(this.instance.$createAS2Script(actionsData));
}
this.as2ActionsCache[buttonCondition] = buttonActionsCache;
}
for (var i = 0; i < buttonActionsCache.length; i++)
buttonActionsCache[i].call(this.instance);
},
onMouseWheel: function () {}
};
this._timelineLoader = timelineLoader;
var proto = MovieClipClass.apply(this, arguments) || this;
proto.nativeObjectContructor = AS2Button;
proto.buttonActions = obj.buttonActions;
proto.constructor = (function(oldContructor) {
return (function() {
var result = oldContructor.apply(this, arguments);
result.gotoAndStop(4); // invoke hitTest layer
result.gotoAndStop(1); // then return to the normal
result.renderNextFrame = (function(oldRenderNextFrame) {
return (function(context) {
if (!context.isHitTestRendering)
return oldRenderNextFrame.apply(this, arguments);
var displayList = this.$getDisplayList(4);
if (!displayList)
return; // skiping non-prepared frame
render(displayList, context);
});
})(result.renderNextFrame);
AS2Mouse.addListener(new ButtonEvents(result));
return result;
});
})(proto.constructor);
return proto;
};
// HACK mocking the sound clips presence
var SoundMock = function(assets) {
var clip = {
start: function() {},
setVolume: function() {}
};
var as2Object = {};
for (var i = 0; i < assets.length; i++)
if (assets[i].className)
as2Object[assets[i].className] = clip;
this.$as2Object = as2Object;
};

Просмотреть файл

@ -1,158 +1,7 @@
/* -*- 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");
const ContainerClass = avm2.systemDomain.getClass("flash.display.DisplayObjectContainer");
function visitContainer(container, visitor) {
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);
visitor.visit(child, isContainer);
if (isContainer) {
visitContainer(child, visitor);
}
}
}
visitor.childrenEnd(container);
}
function EnterFrameVisitor() {
}
EnterFrameVisitor.prototype = {
childrenStart: function() {},
childrenEnd: function() {},
visit: function (obj) {
if (MovieClipClass.isInstanceOf(obj)) {
if (obj.isPlaying()) {
obj.nextFrame();
}
obj.dispatchEvent(new flash.events.Event("enterFrame"));
}
}
};
function ExitFrameVisitor() {
}
ExitFrameVisitor.prototype = {
childrenStart: function() {},
childrenEnd: function() {},
visit: function (obj) {
if (MovieClipClass.isInstanceOf(obj)) {
obj.dispatchEvent(new flash.events.Event("exitFrame"));
}
}
};
function RenderVisitor(ctx) {
this.depth = 0;
this.ctx = ctx;
}
RenderVisitor.prototype = {
childrenStart: function(parent) {
if (this.depth == 0) {
var ctx = this.ctx;
var stage = parent;
var frameWidth = ctx.canvas.width;
var frameHeight = ctx.canvas.height;
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;
ctx.clearRect(0, 0, frameWidth, frameHeight);
ctx.save();
ctx.translate(offsetX, offsetY);
ctx.canvas.currentTransform = {
scale: scale,
offsetX: offsetX,
offsetY: offsetY
};
}
this.depth++;
// TODO move into separate visitor?
if (MovieClipClass.isInstanceOf(parent) && parent._scriptExecutionPending) {
parent.callFrame(parent.currentFrame);
parent._scriptExecutionPending = false;
}
},
childrenEnd: function(parent) {
this.depth--;
this.ctx.restore();
},
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;
function renderDisplayObject(child, ctx, transform, cxform) {
var m = transform;
ctx.transform(m.a, m.b, m.c, m.d, m.tx, m.ty);
var cxform = child._cxform;
if (cxform) {
// We only support alpha channel transformation for now
ctx.globalAlpha = (ctx.globalAlpha * cxform.alphaMultiplier + cxform.alphaOffset) / 256;
@ -167,11 +16,12 @@ function renderStage(stage, ctx) {
var subpaths = graphics._subpaths;
for (var j = 0, o = subpaths.length; j < o; j++) {
var path = subpaths[j];
var pathTracker = subpaths[j], path = pathTracker.target;
if (path.fillStyle) {
ctx.fillStyle = path.fillStyle;
if (path.fillTransform) {
var m = path.fillTransform;
ctx.beginPath();
path.__draw__(ctx);
ctx.save();
ctx.transform(m.a, m.b, m.c, m.d, m.tx, m.ty);
@ -183,7 +33,7 @@ function renderStage(stage, ctx) {
}
if (path.strokeStyle) {
ctx.strokeStyle = path.strokeStyle;
var drawingStyles = path.drawingStyles;
var drawingStyles = pathTracker.drawingStyles;
for (var prop in drawingStyles)
ctx[prop] = drawingStyles[prop];
ctx.stroke(path);
@ -191,74 +41,245 @@ function renderStage(stage, ctx) {
}
}
if (child.draw) {
if (child.draw)
child.draw(ctx, child.ratio);
}
function renderStage(stage, ctx, onFrame) {
var frameWidth = ctx.canvas.width;
var frameHeight = ctx.canvas.height;
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;
ctx.translate(offsetX, offsetY);
ctx.scale(scale, scale);
// All the visitors close over this class to do instance testing.
var MovieClipClass = avm2.systemDomain.getClass("flash.display.MovieClip");
var ContainerClass = avm2.systemDomain.getClass("flash.display.DisplayObjectContainer");
var SimpleButtonClass = avm2.systemDomain.getClass("flash.display.SimpleButton");
var InteractiveClass = avm2.systemDomain.getClass("flash.display.InteractiveObject");
function visitContainer(container, visitor, interactiveParent) {
var children = container._children;
var dirty = false;
visitor.childrenStart(container);
for (var i = 0, n = children.length; i < n; i++) {
var child = children[i];
if (child) {
var isContainer = ContainerClass.isInstanceOf(child) ||
SimpleButtonClass.isInstanceOf(child);
if (InteractiveClass.isInstanceOf(child) && child._mouseEnabled) {
if (!interactiveParent || interactiveParent._mouseChildren)
interactiveParent = child;
}
visitor.visit(child, isContainer, interactiveParent);
if (isContainer)
visitContainer(child, visitor, interactiveParent);
if (child._dirtyArea)
dirty = true;
}
}
visitor.childrenEnd(container);
if (dirty)
container._bounds = null;
}
function PreVisitor(ctx) {
this.ctx = ctx;
}
PreVisitor.prototype = {
childrenStart: function() {},
childrenEnd: function() {},
visit: function (child, isContainer, interactiveParent) {
if (MovieClipClass.isInstanceOf(child)) {
if (child.isPlaying()) {
child.nextFrame();
}
child.dispatchEvent(new flash.events.Event("enterFrame"));
}
if (child._refreshAS2Variables) {
child._refreshAS2Variables();
}
var mouseMoved = false;
var pt = { x: stage._mouseX, y: stage._mouseY };
child._applyCurrentInverseTransform(pt, child._parent);
if (pt.x !== child._mouseX || pt.y !== child._mouseY)
mouseMoved = true;
child._mouseX = pt.x;
child._mouseY = pt.y;
if (interactiveParent && (stage._mouseOver || stage._mouseJustLeft)) {
var hitArea = child._hitArea || child;
if (child._hitTest(true, pt.x, pt.y, true, true)) {
if (interactiveParent._mouseOver) {
if (mouseMoved)
interactiveParent.dispatchEvent(new flash.events.MouseEvent('mouseMove'));
} else {
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._clickTarget === interactiveParent)
stage._clickTarget = null;
}
stage._mouseJustLeft = false;
}
if (child._dirtyArea) {
var b1 = child._dirtyArea;
var b2 = child.getBounds();
this.ctx.rect((~~b1.x) - 5, (~~b1.y) - 5, (~~b1.width) + 10, (~~b1.height) + 10);
this.ctx.rect((~~b2.x) - 5, (~~b2.y) - 5, (~~b2.width) + 10, (~~b2.height) + 10);
} else if (child._graphics && (child._graphics._revision !== child._revision)) {
child._revision = child._graphics._revision;
child._markAsDirty();
// redraw entire stage till we calculate bounding boxes for dynamic graphics
this.ctx.rect(0, 0, frameWidth, frameHeight);
}
}
};
function PostVisitor() {
}
PostVisitor.prototype = {
childrenStart: function() {},
childrenEnd: function() {},
visit: function (child) {
if (MovieClipClass.isInstanceOf(child))
child.dispatchEvent(new flash.events.Event("exitFrame"));
}
};
function ScriptExecutionVisitor() {}
ScriptExecutionVisitor.prototype = {
childrenStart: function() {},
childrenEnd: function() {},
visit: function (obj) {
if (obj._scriptExecutionPending) {
obj._scriptExecutionPending = false;
var currentFrame = obj._currentFrame;
obj._callFrame(currentFrame);
}
}
};
function RenderVisitor(ctx) {
this.ctx = ctx;
this.depth = 0;
}
RenderVisitor.prototype = {
childrenStart: function(parent) {
if (this.depth == 0) {
var ctx = this.ctx;
ctx.save();
ctx.clip();
ctx.clearRect(0, 0, frameWidth, frameHeight);
ctx.mozFillRule = 'evenodd';
stage._canvasState = {
canvas: ctx.canvas,
scale: scale,
offsetX: offsetX,
offsetY: offsetY
};
}
this.depth++;
},
childrenEnd: function(parent) {
this.depth--;
this.ctx.restore();
},
visit: function (child, isContainer) {
if (child._clipDepth) {
// TODO handle masking
return;
}
var ctx = this.ctx;
ctx.save();
renderDisplayObject(child, ctx, child._currentTransform, child._cxform);
if (!isContainer) {
// letting the container to restore transforms after all children are painted
ctx.restore();
}
//if (child.hitTestCache && child.hitTestCache.ratio != child.ratio)
// renderShadowCanvas(child);
if (stage._showRedrawRegions && child._dirtyArea) {
var b = child._dirtyArea;
ctx.save();
ctx.strokeStyle = '#f00';
ctx.lineWidth = 1;
ctx.strokeRect(b.x, b.y, b.width, b.height);
ctx.restore();
}
child._dirtyArea = null;
}
};
var frameTime = 0;
var maxDelay = 1000 / stage.frameRate;
ctx.mozFillRule = 'evenodd';
var requestAnimationFrame = window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame;
var FPS = (function () {
var width = Math.max(ctx.canvas.width / 5, 100);
var height = width / 8;
var sampleWidth = 2;
var sampleCount = width / (sampleWidth + 1);
var last = null;
var samples = [];
var max = 0;
return {
tick: function () {
var curr = new Date();
if (last) {
if (samples.length > sampleCount) {
samples.shift();
}
var elapsed = curr - last;
samples.push(elapsed);
var sum = 0;
for (var i = 0; i < samples.length; i++) {
sum += samples[i];
max = Math.max(max, samples[i]);
}
var avg = sum / samples.length;
var xOffset = ctx.canvas.width - width;
var yOffset = height;
for (var i = 0; i < samples.length; i++) {
var scaledSample = (samples[i] / (2 * avg));
ctx.fillRect(xOffset + i * (sampleWidth + 1), yOffset, sampleWidth, - scaledSample * height);
}
ctx.font = "6pt Verdana";
ctx.fillText("FPS: " + (1000 / avg).toFixed(2), xOffset, height + 15);
}
last = curr;
}
};
})();
var requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.setTimeout;
(function draw() {
var now = +new Date;
if (now - frameTime >= maxDelay) {
frameTime = now;
visitContainer(stage, new EnterFrameVisitor());
ctx.beginPath();
stage._callFrameRequested = false;
visitContainer(stage, new PreVisitor(ctx));
while (stage._callFrameRequested) {
stage._callFrameRequested = false;
visitContainer(stage, new ScriptExecutionVisitor());
}
visitContainer(stage, new RenderVisitor(ctx));
visitContainer(stage, new ExitFrameVisitor());
FPS.tick();
visitContainer(stage, new PostVisitor());
stage._syncCursor();
if (onFrame) {
onFrame();
}
}
requestAnimationFrame(draw);
})();

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше