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/asc.jar
src/avm2/utils/avmshell src/avm2/utils/avmshell
src/avm2/utils/js src/avm2/utils/js
src/flash/playerGlobal.min.abc

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

@ -4,3 +4,6 @@
[submodule "lib/DataView.js"] [submodule "lib/DataView.js"]
path = lib/DataView.js path = lib/DataView.js
url = https://github.com/davidflanagan/DataView.js.git 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: default:
@echo "run: make [check-system|install-utils|install-libs|build-tamarin-tests|" @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: check-system:
echo "Checking the presence of mercurial..." echo "Checking the presence of mercurial..."
@ -32,10 +33,33 @@ build-playerglobal:
build-extension: build-extension:
make -C extension/firefox/ build 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: test:
make -C src/avm1/tests/ test make -C src/avm1/tests/ test
make -C src/avm2/bin/ test-regress 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: hello-world:
make -C src/avm2/bin/ hello-world make -C src/avm2/bin/ hello-world
@ -86,4 +110,7 @@ start-build-bot:
sleep 60 ; \ sleep 60 ; \
done 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"> <link rel="stylesheet" href="style/style.css">
</head> </head>
<body> <body>
<div id="stage"></div> <div id="stage">
<div id="xstats"></div>
</div>
<script src="jquery.min.js"></script> <script src="jquery.min.js"></script>
<script src="../../lib/DataView.js/DataView.js"></script> <script src="../../lib/DataView.js/DataView.js"></script>
<script src="../../lib/Kanvas/kanvas.js"></script> <script src="../../lib/Kanvas/kanvas.js"></script>
<script src="../../lib/xstats/xstats.js"></script>
<!-- Load SWF Dependencies --> <!-- Load SWF Dependencies -->
<script src="../../src/swf/util.js"></script> <script src="../../src/swf/util.js"></script>
@ -96,46 +99,53 @@
<!-- Load Flash Dependencies --> <!-- Load Flash Dependencies -->
<script src="../../src/flash/util.js"></script> <script src="../../src/flash/util.js"></script>
<script src="../../src/flash/events/Event.js"></script> <!-- Autogenerated flash references: base=../../src/flash/ -->
<script src="../../src/flash/events/KeyboardEvent.js"></script> <script src="../../src/flash/display/Bitmap.js"></script>
<script src="../../src/flash/events/TimerEvent.js"></script> <script src="../../src/flash/display/BitmapData.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>
<script src="../../src/flash/display/DisplayObject.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/DisplayObjectContainer.js"></script>
<script src="../../src/flash/display/Sprite.js"></script> <script src="../../src/flash/display/Graphics.js"></script>
<script src="../../src/flash/display/MovieClip.js"></script> <script src="../../src/flash/display/InteractiveObject.js"></script>
<script src="../../src/flash/display/Loader.js"></script> <script src="../../src/flash/display/Loader.js"></script>
<script src="../../src/flash/display/LoaderInfo.js"></script> <script src="../../src/flash/display/LoaderInfo.js"></script>
<script src="../../src/flash/display/Stage.js"></script> <script src="../../src/flash/display/MorphShape.js"></script>
<script src="../../src/flash/display/BitmapData.js"></script> <script src="../../src/flash/display/MovieClip.js"></script>
<script src="../../src/flash/display/Graphics.js"></script>
<script src="../../src/flash/display/Shape.js"></script> <script src="../../src/flash/display/Shape.js"></script>
<script src="../../src/flash/display/SimpleButton.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/Point.js"></script>
<script src="../../src/flash/geom/Rectangle.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/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/SoundTransform.js"></script>
-->
<script src="../../src/flash/media/Video.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/Font.js"></script>
-->
<script src="../../src/flash/text/StaticText.js"></script> <script src="../../src/flash/text/StaticText.js"></script>
<script src="../../src/flash/text/TextField.js"></script> <script src="../../src/flash/text/TextField.js"></script>
<script src="../../src/flash/ui/Keyboard.js"></script> <script src="../../src/flash/ui/Keyboard.js"></script>
<!--
<script src="../../src/flash/ui/Mouse.js"></script> <script src="../../src/flash/ui/Mouse.js"></script>
-->
<script src="../../src/flash/utils/Timer.js"></script> <script src="../../src/flash/utils/Timer.js"></script>
<!-- Autogenerated flash references end -->
<script src="../../src/flash/stubs.js"></script> <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: Shameless copying from:
@ -143,9 +153,13 @@
--> -->
<div class="toolbarGroup"> <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 class="toolbarInfo" style="position: fixed; bottom: 70px; left: auto; right: 0px; width: 300px; height: 300px;" id="info">
</div> </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="closeButton"></div>
<div class="toolbarLabel " style="width: 140px; text-align: left;">Shumway Inspector</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> <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 src="inspector.js"></script>
<script> <script>
SHUMWAY_ROOT = "../../"; SHUMWAY_ROOT = "../../src/";
</script>
<script>
var stats = new xStats;
document.getElementById('xstats').appendChild(stats.element);
</script> </script>
</body> </body>

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

@ -65,13 +65,19 @@ var playerGlobalPath = "../../src/flash/playerGlobal.min.abc";
* when the page loads. * when the page loads.
*/ */
if (rfile) { if (rfile) {
$('#openFileToolbar')[0].setAttribute('hidden', true);
executeFile(rfile); executeFile(rfile);
} }
function showMessage(msg) {
$('#message').text(msg);
$('#message')[0].parentElement.removeAttribute('hidden');
}
function executeFile(file, buffer) { function executeFile(file, buffer) {
// All execution paths must now load AVM2. // All execution paths must now load AVM2.
if (!state.compiler) { if (!state.compiler) {
alert ("Running in the Interpreter"); showMessage("Running in the Interpreter");
} }
var appMode = state.compiler ? EXECUTION_MODE.COMPILE : EXECUTION_MODE.INTERPRET; var appMode = state.compiler ? EXECUTION_MODE.COMPILE : EXECUTION_MODE.INTERPRET;
if (file.endsWith(".abc")) { if (file.endsWith(".abc")) {

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

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

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

@ -1,5 +1,11 @@
function loadState() { 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) { function saveState(state) {

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

@ -1,4 +1,4 @@
html html
{ {
height: 100%; height: 100%;
} }
@ -12,7 +12,7 @@ body {
@media screen and (-webkit-min-device-pixel-ratio:0) { @media screen and (-webkit-min-device-pixel-ratio:0) {
body { body {
background: #1a2633; background-color: #1a2633;
} }
} }
@ -22,35 +22,50 @@ body {
} }
.toolbarInfo { .toolbarInfo {
padding: 4px 8px; font-family: Consolas, Lucida Grande, sans-serif;
background: url(images/background-noise-toolbar.png),
-moz-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 0 0 1px hsla(210,16%,76%,.15) inset, padding: 4px 8px;
0 1px 0 hsla(210,16%,76%,.15); background-image: url(images/background-noise-toolbar.png),
color: hsl(210,30%,85%); linear-gradient(hsl(210,11%,36%), hsl(210,11%,18%));
font-size: 10px; background-image: url(images/background-noise-toolbar.png),
line-height: 22px; -moz-linear-gradient(hsl(210,11%,36%), hsl(210,11%,18%));
text-shadow: 0 -1px 0 hsla(210,8%,5%,.45); background-image: url(images/background-noise-toolbar.png),
cursor: default; -webkit-linear-gradient(hsl(210,11%,36%), hsl(210,11%,18%));
background-image: url(images/background-noise-toolbar.png),
line-height: 1.2em; -o-linear-gradient(hsl(210,11%,36%), hsl(210,11%,18%));
font-size: 11px; background-image: url(images/background-noise-toolbar.png),
-ms-linear-gradient(hsl(210,11%,36%), hsl(210,11%,18%));
overflow-x: auto; 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),
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: 10px;
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;
} }
.toolbarBox { .toolbarBox {
padding: 4px 8px; padding: 4px 8px;
width: 600px; width: 600px;
height: 24px; 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), background: url(images/background-noise-toolbar.png),
-moz-linear-gradient(hsl(210,11%,36%), hsl(210,11%,18%)); -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; border-radius: 4px;
box-shadow: 0 1px 0 hsla(210,16%,76%,.2) inset, box-shadow: 0 1px 0 hsla(210,16%,76%,.2) inset,
0 0 0 1px hsla(0,0%,0%,.15), 0 0 0 1px hsla(0,0%,0%,.15),
@ -58,6 +73,24 @@ body {
font-family: Lucida Grande, sans-serif; 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 { .closeButton {
float: left; float: left;
width: 16px; width: 16px;
@ -75,19 +108,21 @@ body {
} }
.toolbarLabel { .toolbarLabel {
float: left; float: left;
width: 78px; width: 78px;
height: 22px; height: 22px;
margin-right: 10px; margin-right: 10px;
0 0 0 1px hsla(210,16%,76%,.15) inset, color: hsl(210,30%,85%);
0 1px 0 hsla(210,16%,76%,.15); font-size: 12px;
color: hsl(210,30%,85%); line-height: 22px;
font-size: 12px; text-align: center;
line-height: 22px; text-shadow: 0 -1px 0 hsla(210,8%,5%,.45);
text-align: center; user-select: none;
text-shadow: 0 -1px 0 hsla(210,8%,5%,.45); -moz-user-select: none;
-moz-user-select: none; -webkit-user-select: none;
cursor: default; -o-user-select: none;
-ms-user-select: none;
cursor: default;
} }
.toolbarButton { .toolbarButton {
@ -97,7 +132,11 @@ body {
margin-right: 10px; margin-right: 10px;
border: 1px solid hsla(210,8%,5%,.45); border: 1px solid hsla(210,8%,5%,.45);
border-radius: 3px; 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: -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; background-clip: padding-box;
box-shadow: 0 1px 0 hsla(210,16%,76%,.15) inset, box-shadow: 0 1px 0 hsla(210,16%,76%,.15) inset,
0 0 0 1px hsla(210,16%,76%,.15) inset, 0 0 0 1px hsla(210,16%,76%,.15) inset,
@ -107,13 +146,21 @@ body {
line-height: 22px; line-height: 22px;
text-align: center; text-align: center;
text-shadow: 0 -1px 0 hsla(210,8%,5%,.45); text-shadow: 0 -1px 0 hsla(210,8%,5%,.45);
user-select: none;
-moz-user-select: none; -moz-user-select: none;
-webkit-user-select: none;
-o-user-select: none;
-ms-user-select: none;
cursor: default; cursor: default;
} }
.toolbarButton:not(.pressedState):hover:active { .toolbarButton:not(.pressedState):hover:active {
border: 1px solid hsla(210,8%,5%,.6); 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: -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, box-shadow: 0 0 3px hsla(210,8%,5%,.25) inset,
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); 0 1px 0 hsla(210,16%,76%,.15);
@ -121,7 +168,11 @@ body {
.toolbarButton.pressedState { .toolbarButton.pressedState {
border: 1px solid hsla(210,8%,5%,.6); 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: -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, box-shadow: 0 1px 3px hsla(210,8%,5%,.25) inset,
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); 0 1px 0 hsla(210,16%,76%,.15);
@ -142,7 +193,11 @@ body {
line-height: 22px; line-height: 22px;
text-align: center; text-align: center;
text-shadow: 0 -1px 0 hsla(210,8%,5%,.45); text-shadow: 0 -1px 0 hsla(210,8%,5%,.45);
user-select: none;
-moz-user-select: none; -moz-user-select: none;
-webkit-user-select: none;
-o-user-select: none;
-ms-user-select: none;
cursor: default; cursor: default;
} }
@ -151,10 +206,18 @@ body {
padding: 0 4px; padding: 0 4px;
height: 24px; height: 24px;
border-width: 0 13px 0 8px; 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; -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 { .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; -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 { .breadcrumbBarMiddle {
@ -163,10 +226,18 @@ body {
float: left; float: left;
height: 24px; height: 24px;
border-width: 0 13px; 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; -moz-border-image: url(images/breadcrumb-mac-middle.png) 0 13 0 13 repeat;
} }
.breadcrumbBarMiddle:hover:active { .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; -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 { .breadcrumbBarEnd {
@ -175,37 +246,70 @@ body {
float: left; float: left;
height: 24px; height: 24px;
border-width: 0 8px 0 13px; 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; -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%); color: hsl(208,100%,60%);
} }
.breadcrumbBarEnd:hover:active { .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; -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 { .textInput {
float: left; float: left;
-moz-appearance: none; appearance: none;
margin: 0 3px; -moz-appearance: none;
background-color: transparent; -webkit-appearance: none;
height: 22px; -o-appearance: none;
border: 1px solid hsla(210,8%,5%,.6); -ms-appearance: none;
border-radius: 6px; margin: 0 3px;
background-image: -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35)); background-color: transparent;
background-repeat: no-repeat; height: 22px;
background-position: 4px center, top left, top left; border: 1px solid hsla(210,8%,5%,.6);
padding-top: 0; border-radius: 6px;
padding-bottom: 0; background-image: linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
-moz-padding-start: 10px; background-image: -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
-moz-padding-end: 4px; background-image: -webkit-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
box-shadow: 0 1px 1px hsla(210,8%,5%,.3) inset, background-image: -o-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
0 0 0 1px hsla(210,16%,76%,.1) inset, background-image: -ms-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
0 1px 0 hsla(210,16%,76%,.15); background-repeat: no-repeat;
color: hsl(210,30%,85%); background-position: 4px center, top left, top left;
font-weight: bolder; 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) { .textInput:-moz-locale-dir(rtl) {
background-position: calc(100% - 4px) center, top left, top left; 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; color: Yellow;
} }
</style> </style>
</head>
<body> <script>
<div id="stage"></div> SHUMWAY_ROOT = "../../src/";
</script>
<script src="../../lib/DataView.js/DataView.js"></script> <script src="../../lib/DataView.js/DataView.js"></script>
<script src="../../lib/Kanvas/kanvas.js"></script> <script src="../../lib/Kanvas/kanvas.js"></script>
@ -50,9 +51,6 @@
<script src="../../src/swf/shape.js"></script> <script src="../../src/swf/shape.js"></script>
<script src="../../src/swf/text.js"></script> <script src="../../src/swf/text.js"></script>
<script src="../../src/swf/prototypes.js"></script>
<!-- Load AVM1 Dependencies --> <!-- Load AVM1 Dependencies -->
<script src="../../src/avm1/classes.js"></script> <script src="../../src/avm1/classes.js"></script>
<script src="../../src/avm1/globals.js"></script> <script src="../../src/avm1/globals.js"></script>
@ -61,29 +59,108 @@
<script src="../../src/swf/embed.js"></script> <script src="../../src/swf/embed.js"></script>
<script src="../../src/swf/renderer.js"></script> <script src="../../src/swf/renderer.js"></script>
<script src="../../src/flash/util.js"></script> <!-- Load AVM2 Dependencies -->
<script src="../../src/flash/events/Event.js"></script> <script src="../../src/avm2/util.js"></script>
<script src="../../src/flash/events/ProgressEvent.js"></script> <script src="../../src/avm2/options.js"></script>
<script src="../../src/flash/events/EventDispatcher.js"></script> <script src="../../src/avm2/metrics.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>
<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>
<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> <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> </script>
<div id="footer"> <div id="footer">
<sup>*</sup> <sup>*</sup>

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

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

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

@ -1,6 +1,63 @@
# Just builds a ff extension # 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 # Cleaning old files
-rm -rf content/swf -rm -rf content/swf
-rm -rf content/flash -rm -rf content/flash
@ -8,40 +65,7 @@ build:
-rm -rf content/avm2 -rm -rf content/avm2
-rm -rf content/glue -rm -rf content/glue
-rm -rf content/lib -rm -rf content/lib
-rm LICENSE
-rm shumway.xpi -rm shumway.xpi
# Coping JavaScript content files
mkdir content/swf PHONY: build clean legacy-clean
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

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

@ -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"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>Shumway viewer</title> <title>Shumway viewer</title>
<script>
SHUMWAY_ROOT = "resource://shumway/";
</script>
<!-- <base href="resource://shumway/web/viewer.html" /> --> <!-- <base href="resource://shumway/web/viewer.html" /> -->
<script src="../lib/DataView.js/DataView.js"></script> <script src="../lib/DataView.js/DataView.js"></script>
<script src="../lib/Kanvas/kanvas.js"></script> <script src="../lib/Kanvas/kanvas.js"></script>
@ -28,9 +32,6 @@
<script src="../swf/shape.js"></script> <script src="../swf/shape.js"></script>
<script src="../swf/text.js"></script> <script src="../swf/text.js"></script>
<script src="../swf/prototypes.js"></script>
<!-- Load AVM1 Dependencies --> <!-- Load AVM1 Dependencies -->
<script src="../avm1/classes.js"></script> <script src="../avm1/classes.js"></script>
<script src="../avm1/globals.js"></script> <script src="../avm1/globals.js"></script>
@ -39,22 +40,90 @@
<script src="../swf/embed.js"></script> <script src="../swf/embed.js"></script>
<script src="../swf/renderer.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/util.js"></script>
<script src="../flash/events/EventPhase.js"></script> <!-- Autogenerated flash references: base=../flash/ -->
<script src="../flash/events/Event.js"></script> <script src="../flash/display/Bitmap.js"></script>
<script src="../flash/events/ProgressEvent.js"></script> <script src="../flash/display/BitmapData.js"></script>
<script src="../flash/events/EventDispatcher.js"></script>
<script src="../flash/display/DisplayObject.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/DisplayObjectContainer.js"></script>
<script src="../flash/display/Graphics.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/Loader.js"></script>
<script src="../flash/display/LoaderInfo.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/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/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/Keyboard.js"></script>
<script src="../flash/ui/Mouse.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> <script>
// Extenstion communication object... as it used in pdf.js // Extenstion communication object... as it used in pdf.js
@ -151,29 +220,41 @@
function parseSwf(url, file) { function parseSwf(url, file) {
console.log("Parsing " + url + "..."); 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> </script>
<style> <style>
#viewer { body {
position:fixed;left:0;top:0;bottom:0;right:0; margin: 0;
background-color:magenta; overflow: hidden;
} }
#viewer {
position:fixed;
left:0;top:0;bottom:0;right:0;
overflow: hidden;
/* background-color:magenta; */
}
#fallback { #fallback {
display: none; display: none;
} }
#fallback.enabled { #fallback.enabled {
display: block; display: block;
position:fixed; right: 10px; bottom: 10px; width: 70px; height: 14px; position:fixed;
right: 10px; bottom: 10px; width: 70px; height: 16px;
color: white; color: white;
background-color: #400040; background-color: #0b3268;
font: bold 10px sans-serif; font: bold 10px sans-serif;
text-align: center; text-align: center;
text-decoration: none; text-decoration: none;
border-radius: 5px; border-radius: 5px;
box-shadow: 0px 0px 3px 3px #888; box-shadow: 0px 0px 2px 2px #888;
} }
#fallback .icon { #fallback .icon {
display: inline-block; display: inline-block;
@ -184,6 +265,6 @@
<body onload="runViewer()"> <body onload="runViewer()">
<div id="viewer"></div> <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> </body>
</html> </html>

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

@ -5,16 +5,16 @@
<Description about="urn:mozilla:install-manifest"> <Description about="urn:mozilla:install-manifest">
<em:id>shumway@research.mozilla.org</em:id> <em:id>shumway@research.mozilla.org</em:id>
<em:name>shumway</em:name> <em:name>Shumway</em:name>
<em:version>0.2.1</em:version> <em:version>(SHUMWAY_VERSION)</em:version>
<em:iconURL>chrome://shumway/skin/logo.png</em:iconURL> <em:iconURL>chrome://shumway/skin/logo.png</em:iconURL>
<!-- Firefox --> <!-- Firefox -->
<em:targetApplication> <em:targetApplication>
<Description> <Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>10.0</em:minVersion> <em:minVersion>17.0</em:minVersion>
<em:maxVersion>17.0a1</em:maxVersion> <em:maxVersion>19.0a1</em:maxVersion>
</Description> </Description>
</em:targetApplication> </em:targetApplication>
@ -22,16 +22,18 @@
<em:targetApplication> <em:targetApplication>
<Description> <Description>
<em:id>{aa3c5121-dab2-40e2-81ca-7ea25febc110}</em:id> <em:id>{aa3c5121-dab2-40e2-81ca-7ea25febc110}</em:id>
<em:minVersion>10.0</em:minVersion> <em:minVersion>17.0</em:minVersion>
<em:maxVersion>17.0a1</em:maxVersion> <em:maxVersion>19.0a1</em:maxVersion>
</Description> </Description>
</em:targetApplication> </em:targetApplication>
<em:bootstrap>true</em:bootstrap> <em:bootstrap>true</em:bootstrap>
<em:unpack>true</em:unpack> <em:unpack>true</em:unpack>
<em:creator>Mozilla Research</em:creator> <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:homepageURL>https://github.com/mozilla/shumway/</em:homepageURL>
<em:type>2</em:type> <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> </Description>
</RDF> </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 nativeCanvasProto = nativeCanvasClass.prototype;
var native2dContextProto = native2dContextClass.prototype; var native2dContextProto = native2dContextClass.prototype;
var kanvas2dContextProto = Object.create(native2dContextProto);
var matrixClass; var matrixClass;
var pathClass; var pathClass;
var wrap2dContext;
var shimCurrentTransform = !('currentTransform' in native2dContext); var shimCurrentTransform = !('currentTransform' in native2dContext);
var shimPath = typeof Path === 'undefined'; var shimPath = typeof Path === 'undefined';
@ -44,7 +44,7 @@
val = desc.get.call(this); val = desc.get.call(this);
defineProperty(this, prop, { defineProperty(this, prop, {
value: val, value: val,
writable: desc.writable, writable: true, // some browsers need that to be true
configurable: desc.configurable, configurable: desc.configurable,
enumerable: desc.enumerable enumerable: desc.enumerable
}); });
@ -74,8 +74,7 @@
var context; var context;
if (contextId === 'kanvas-2d') { if (contextId === 'kanvas-2d') {
context = nativeGetContext.call(this, '2d'); context = wrap2dContext(nativeGetContext.call(this, '2d'));
context.__proto__ = kanvas2dContextProto;
} else { } else {
context = nativeGetContext.apply(this, arguments); context = nativeGetContext.apply(this, arguments);
} }
@ -87,15 +86,17 @@
}; };
try { try {
var matrix = new SVGMatrix; if (typeof SVGMatrix !== 'undefined')
matrixClass = matrix.constructor; matrixClass = (new SVGMatrix).constructor;
} catch (err) { } catch (err) { }
if (!matrixClass) {
var svgNamespace = 'http://www.w3.org/2000/svg'; var svgNamespace = 'http://www.w3.org/2000/svg';
var svgElement = document.createElementNS(svgNamespace, 'svg'); var svgElement = document.createElementNS(svgNamespace, 'svg');
matrixClass = function SVGMatrix() { matrixClass = function SVGMatrix() {
return svgElement.createSVGMatrix(); return svgElement.createSVGMatrix();
} };
matrixClass.prototype = SVGMatrix.prototype; matrixClass.prototype = SVGMatrix.prototype;
} }
@ -105,8 +106,11 @@
return new Path(d); return new Path(d);
var displayList = []; var displayList = [];
var hitCanvas = nativeCanvas.cloneNode();
var hitCanvas = document.createElement('canvas');
hitCanvas.width = hitCanvas.height = 1;
var hitContext = hitCanvas.getContext('2d'); var hitContext = hitCanvas.getContext('2d');
var pathState = [Number.MAX_VALUE, 0, Number.MAX_VALUE, 0]; var pathState = [Number.MAX_VALUE, 0, Number.MAX_VALUE, 0];
defineProperties(this, { defineProperties(this, {
@ -225,7 +229,7 @@
defineLazyProperty(pathProto, '__draw__', { defineLazyProperty(pathProto, '__draw__', {
get: function () { get: function () {
return Function('c', this.__displayList__.join(';')); return new Function('c', this.__displayList__.join(';'));
} }
}); });
@ -240,19 +244,30 @@
pathClass.prototype = pathProto; pathClass.prototype = pathProto;
['fill', 'stroke', 'clip'].forEach(function (methodName) { wrap2dContext = (function () {
var nativeMethod = kanvas2dContextProto[methodName]; 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);
kanvas2dContextProto[methodName] = function (path) { return function wrap2dContext(ctx) {
if (path instanceof pathClass) { ctx.fill = wrappedFillMethod;
this.beginPath(); ctx.stroke = wrappedStrokeMethod;
path.__draw__(this); ctx.clip = wrappedClipMethod;
} return ctx;
nativeMethod.call(this);
}; };
}); })();
} else { } else {
pathClass = Path; pathClass = Path;
wrap2dContext = function(ctx) { return ctx; };
} }
Kanvas.SVGMatrix = matrixClass; Kanvas.SVGMatrix = matrixClass;

1
lib/xstats Submodule

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

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

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

@ -32,23 +32,29 @@ AS2Globals.prototype = {
nativeTarget.duplicateMovieClip(newname, depth); nativeTarget.duplicateMovieClip(newname, depth);
}, },
fscommand: function (command, parameters) { 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) { getProperty: function(target, index) {
var nativeTarget = AS2Context.instance.resolveTarget(target); var nativeTarget = AS2Context.instance.resolveTarget(target);
return nativeTarget[PropertiesIndexMap[index]]; return nativeTarget[PropertiesIndexMap[index]];
}, },
getTimer: function() { 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) { getURL: function(url, target, method) {
var request = new AS2URLRequest(url); var request = new flash.net.URLRequest(url);
if (method) if (method)
request.method = 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() { getVersion: function() {
return flash.system.Capalilities.version; return flash.system.Capabilities.version;
}, },
gotoAndPlay: function() { gotoAndPlay: function() {
var nativeTarget = AS2Context.instance.resolveTarget(); var nativeTarget = AS2Context.instance.resolveTarget();
@ -83,11 +89,19 @@ AS2Globals.prototype = {
}, },
loadMovie: function(url, target, method) { loadMovie: function(url, target, method) {
var nativeTarget = AS2Context.instance.resolveTarget(target); 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 // flash.display.Loader, flash.net.URLLoader
throw 'Not implemented: loadMovie'; throw 'Not implemented: loadMovie';
}, },
loadMovieNum: function(url, level, method) { loadMovieNum: function(url, level, method) {
var nativeTarget = AS2Context.instance.resolveLevel(level); 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 // flash.display.Loader, flash.net.URLLoader
throw 'Not implemented: loadMovieNum'; throw 'Not implemented: loadMovieNum';
}, },
@ -179,7 +193,8 @@ AS2Globals.prototype = {
nativeTarget.stop(); nativeTarget.stop();
}, },
stopAllSounds: function() { stopAllSounds: function() {
flash.media.SoundMixer.stopAll(); var soundMixerClass = avm2.systemDomain.getClass("flash.media.SoundMixer");
soundMixerClass.native.static.stopAll();
}, },
stopDrag: function(target) { stopDrag: function(target) {
var nativeTarget = AS2Context.instance.resolveTarget(target); var nativeTarget = AS2Context.instance.resolveTarget(target);
@ -190,15 +205,16 @@ AS2Globals.prototype = {
}, },
targetPath: function(target) { targetPath: function(target) {
var nativeTarget = AS2Context.instance.resolveTarget(target); var nativeTarget = AS2Context.instance.resolveTarget(target);
// nativeTarget.getPath() ? return nativeTarget._target;
throw 'Not implemented: targetPath';
}, },
toggleHighQuality: function() { toggleHighQuality: function() {
// flash.display.Stage.quality // flash.display.Stage.quality
throw 'Not implemented: toggleHighQuality'; throw 'Not implemented: toggleHighQuality';
}, },
trace: function(expression) { trace: function(expression) {
console.log(expression); var trace = avm2.applicationDomain.getProperty(
Multiname.fromSimpleName('trace'), true, true);
trace(expression);
}, },
unloadMovie: function(target) { unloadMovie: function(target) {
var nativeTarget = AS2Context.instance.resolveTarget(target); var nativeTarget = AS2Context.instance.resolveTarget(target);
@ -234,6 +250,7 @@ AS2Globals.prototype = {
AsBroadcaster: AS2Broadcaster, AsBroadcaster: AS2Broadcaster,
Stage: AS2Stage, Stage: AS2Stage,
Button: AS2Button, Button: AS2Button,
TextField: AS2TextField,
Rectangle: AS2Rectangle, Rectangle: AS2Rectangle,
Key: AS2Key, Key: AS2Key,
Mouse: AS2Mouse 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; var isAVM1TraceEnabled = false;
@ -17,9 +17,17 @@ function AS2Context(swfVersion) {
this.globals = new AS2Globals(this); this.globals = new AS2Globals(this);
var windowScope = new AS2ScopeListItem(window, null); var windowScope = new AS2ScopeListItem(window, null);
this.initialScope = new AS2ScopeListItem(this.globals, windowScope); this.initialScope = new AS2ScopeListItem(this.globals, windowScope);
this.assets = {};
} }
AS2Context.instance = null; AS2Context.instance = null;
AS2Context.prototype = { 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) { resolveTarget: function(target) {
if (!target) if (!target)
target = this.defaultTarget; 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 actionTracer = ActionTracerFactory.get();
var scopeContainer = context.initialScope.create(scope); var scopeContainer = context.initialScope.create(scope);
@ -43,6 +172,9 @@ function executeActions(actionsData, context, scope) {
try { try {
AS2Context.instance = context; AS2Context.instance = context;
context.defaultTarget = scope; context.defaultTarget = scope;
context.globals['this'] = scope;
if (assets)
context.addAssets(assets);
actionTracer.message('ActionScript Execution Starts'); actionTracer.message('ActionScript Execution Starts');
actionTracer.indent(); actionTracer.indent();
interpretActions(actionsData, scopeContainer, null, []); 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, function interpretActions(actionsData, scopeContainer,
constantPool, registers) { constantPool, registers) {
var currentContext = AS2Context.instance; var currentContext = AS2Context.instance;
@ -61,7 +213,7 @@ function interpretActions(actionsData, scopeContainer,
if (!targetPath) if (!targetPath)
defaultTarget = _global._root; defaultTarget = _global._root;
else else
defaultTarget = defaultTarget.$lookupChild(targetPath); defaultTarget = lookupAS2Children(targetPath, defaultTarget, _global._root);
currentContext.defaultTarget = defaultTarget; currentContext.defaultTarget = defaultTarget;
} }
@ -133,21 +285,12 @@ function interpretActions(actionsData, scopeContainer,
} }
return false; 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) { function resolveVariableName(variableName) {
var obj, name; var obj, name;
if (variableName.indexOf(':') >= 0) { if (variableName.indexOf(':') >= 0) {
// "/A/B:FOO references the FOO variable in the movie clip with a target path of /A/B." // "/A/B:FOO references the FOO variable in the movie clip with a target path of /A/B."
var parts = variableName.split(':'); var parts = variableName.split(':');
var obj = defaultTarget.$lookupChild(parts[0]); var obj = lookupAS2Children(parts[0], defaultTarget, _global._root);
name = parts[1]; name = parts[1];
} else if (variableName.indexOf('.') >= 0) { } else if (variableName.indexOf('.') >= 0) {
// new object reference // new object reference
@ -156,8 +299,9 @@ function interpretActions(actionsData, scopeContainer,
var obj = _global; var obj = _global;
for (var i = 0; i < objPath.length; i++) { for (var i = 0; i < objPath.length; i++) {
obj = obj[objPath[i]]; obj = obj[objPath[i]];
if (!obj) if (!obj) {
throw objPath.slice(0, i + 1) + ' is undefined'; throw objPath.slice(0, i + 1) + ' is undefined';
}
} }
} }
@ -176,6 +320,10 @@ function interpretActions(actionsData, scopeContainer,
if (target) if (target)
return target.obj[target.name]; return target.obj[target.name];
var mc = defaultTarget.$lookupChild(variableName);
if (mc)
return mc;
for (var p = scopeContainer; p; p = p.next) { for (var p = scopeContainer; p; p = p.next) {
if (variableName in p.scope) { if (variableName in p.scope) {
return p.scope[variableName]; return p.scope[variableName];
@ -194,8 +342,8 @@ function interpretActions(actionsData, scopeContainer,
target.obj[target.name] = value; target.obj[target.name] = value;
return; return;
} }
var _this = scope.this || getVariable('this');
scope[variableName] = value; _this[variableName] = value;
} }
function getFunction(functionName) { function getFunction(functionName) {
var fn = getVariable(functionName); var fn = getVariable(functionName);
@ -238,18 +386,29 @@ function interpretActions(actionsData, scopeContainer,
var scope = scopeContainer.scope; var scope = scopeContainer.scope;
var isSwfVersion5 = currentContext.swfVersion >= 5; var isSwfVersion5 = currentContext.swfVersion >= 5;
var actionTracer = ActionTracerFactory.get(); 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) { while (stream.position < stream.end) {
var actionCode = stream.readUI8(); var actionCode = stream.readUI8();
var length = actionCode >= 0x80 ? stream.readUI16() : 0; var length = actionCode >= 0x80 ? stream.readUI16() : 0;
var nextPosition = stream.position + length; nextPosition = stream.position + length;
actionTracer.print(stream.position, actionCode, stack); actionTracer.print(stream.position, actionCode, stack);
switch (actionCode) { switch (actionCode) {
// SWF 3 actions // SWF 3 actions
case 0x81: // ActionGotoFrame case 0x81: // ActionGotoFrame
var frame = stream.readUI16(); var frame = stream.readUI16();
_global.gotoAndPlay(frame); _global.gotoAndPlay(frame + 1);
break; break;
case 0x83: // ActionGetURL case 0x83: // ActionGetURL
var urlString = stream.readString(); var urlString = stream.readString();
@ -278,7 +437,7 @@ function interpretActions(actionsData, scopeContainer,
var frame = stream.readUI16(); var frame = stream.readUI16();
var skipCount = stream.readUI8(); var skipCount = stream.readUI8();
if (!_global.ifFrameLoaded(frame)) if (!_global.ifFrameLoaded(frame))
nextPosition += skipCount; // actions or bytes ? skipActions(skipCount);
break; break;
case 0x8B: // ActionSetTarget case 0x8B: // ActionSetTarget
var targetName = stream.readString(); var targetName = stream.readString();
@ -334,86 +493,85 @@ function interpretActions(actionsData, scopeContainer,
stack.pop(); stack.pop();
break; break;
case 0x0A: // ActionAdd case 0x0A: // ActionAdd
var a = +stack.pop(); var a = as2ToNumber(stack.pop());
var b = +stack.pop(); var b = as2ToNumber(stack.pop());
stack.push(a + b); stack.push(a + b);
break; break;
case 0x0B: // ActionSubtract case 0x0B: // ActionSubtract
var a = +stack.pop(); var a = as2ToNumber(stack.pop());
var b = +stack.pop(); var b = as2ToNumber(stack.pop());
stack.push(b - a); stack.push(b - a);
break; break;
case 0x0C: // ActionMultiply case 0x0C: // ActionMultiply
var a = +stack.pop(); var a = as2ToNumber(stack.pop());
var b = +stack.pop(); var b = as2ToNumber(stack.pop());
stack.push(a * b); stack.push(a * b);
break; break;
case 0x0D: // ActionDivide case 0x0D: // ActionDivide
var a = +stack.pop(); var a = as2ToNumber(stack.pop());
var b = +stack.pop(); var b = as2ToNumber(stack.pop());
var c = b / a; var c = b / a;
stack.push(isSwfVersion5 ? c : isFinite(c) ? c : '#ERROR#'); stack.push(isSwfVersion5 ? c : isFinite(c) ? c : '#ERROR#');
break; break;
case 0x0E: // ActionEquals case 0x0E: // ActionEquals
var a = +stack.pop(); var a = as2ToNumber(stack.pop());
var b = +stack.pop(); var b = as2ToNumber(stack.pop());
var f = a == b; var f = a == b;
stack.push(isSwfVersion5 ? f : f ? 1 : 0); stack.push(isSwfVersion5 ? f : f ? 1 : 0);
break; break;
case 0x0F: // ActionLess case 0x0F: // ActionLess
var a = +stack.pop(); var a = as2ToNumber(stack.pop());
var b = +stack.pop(); var b = as2ToNumber(stack.pop());
var f = b < a; var f = b < a;
stack.push(isSwfVersion5 ? f : f ? 1 : 0); stack.push(isSwfVersion5 ? f : f ? 1 : 0);
break; break;
case 0x10: // ActionAnd case 0x10: // ActionAnd
var a = stack.pop(); var a = as2ToBoolean(stack.pop());
var b = stack.pop(); var b = as2ToBoolean(stack.pop());
var f = a && b; var f = a && b;
stack.push(isSwfVersion5 ? f : f ? 1 : 0); stack.push(isSwfVersion5 ? f : f ? 1 : 0);
break; break;
case 0x11: // ActionOr case 0x11: // ActionOr
var a = stack.pop(); var a = as2ToBoolean(stack.pop());
var b = stack.pop(); var b = as2ToBoolean(stack.pop());
var f = a || b; var f = a || b;
stack.push(isSwfVersion5 ? f : f ? 1 : 0); stack.push(isSwfVersion5 ? f : f ? 1 : 0);
break; break;
case 0x12: // ActionNot case 0x12: // ActionNot
var f = !stack.pop(); var f = !as2ToBoolean(stack.pop());
stack.push(isSwfVersion5 ? f : f ? 1 : 0); stack.push(isSwfVersion5 ? f : f ? 1 : 0);
break; break;
case 0x13: // ActionStringEquals case 0x13: // ActionStringEquals
var sa = '' + stack.pop(); var sa = as2ToString(stack.pop());
var sb = '' + stack.pop(); var sb = as2ToString(stack.pop());
var f = sa == sb; var f = sa == sb;
stack.push(isSwfVersion5 ? f : f ? 1 : 0); stack.push(isSwfVersion5 ? f : f ? 1 : 0);
break; break;
case 0x14: // ActionStringLength case 0x14: // ActionStringLength
case 0x31: // ActionMBStringLength case 0x31: // ActionMBStringLength
stack.push(_global.length(stack.pop())); var sa = as2ToString(stack.pop());
var sa = '' + stack.pop(); stack.push(_global.length(sa));
stack.push(sa.length);
break; break;
case 0x21: // ActionStringAdd case 0x21: // ActionStringAdd
var sa = '' + stack.pop(); var sa = as2ToString(stack.pop());
var sb = '' + stack.pop(); var sb = as2ToString(stack.pop());
stack.push(sb + sa); stack.push(sb + sa);
break; break;
case 0x15: // ActionStringExtract case 0x15: // ActionStringExtract
var count = stack.pop(); var count = stack.pop();
var index = stack.pop(); var index = stack.pop();
var value = stack.pop(); var value = as2ToString(stack.pop());
stack.push(_global.substring(value, index, count)); stack.push(_global.substring(value, index, count));
break; break;
case 0x35: // ActionMBStringExtract case 0x35: // ActionMBStringExtract
var count = stack.pop(); var count = stack.pop();
var index = stack.pop(); var index = stack.pop();
var value = stack.pop(); var value = as2ToString(stack.pop());
stack.push(_global.mbsubstring(value, index, count)); stack.push(_global.mbsubstring(value, index, count));
break; break;
case 0x29: // ActionStringLess case 0x29: // ActionStringLess
var sa = '' + stack.pop(); var sa = as2ToString(stack.pop());
var sb = '' + stack.pop(); var sb = as2ToString(stack.pop());
var f = sb < sa; var f = sb < sa;
stack.push(isSwfVersion5 ? f : f ? 1 : 0); stack.push(isSwfVersion5 ? f : f ? 1 : 0);
break; break;
@ -529,9 +687,7 @@ function interpretActions(actionsData, scopeContainer,
var skipCount = stream.readUI8(); var skipCount = stream.readUI8();
var frame = stack.pop(); var frame = stack.pop();
if (!_global.ifFrameLoaded(frame)) if (!_global.ifFrameLoaded(frame))
nextPosition += skipCount; // actions or bytes ? skipActions(skipCount);
debugger;
//_global.waitForFrame(label, skipCount);
break; break;
case 0x26: // ActionTrace case 0x26: // ActionTrace
var value = stack.pop(); var value = stack.pop();
@ -654,15 +810,23 @@ function interpretActions(actionsData, scopeContainer,
var args = []; var args = [];
for (var i = 0; i < numArgs; i++) for (var i = 0; i < numArgs; i++)
args.push(stack.pop()); args.push(stack.pop());
var result = {}; var method;
if (methodName) { if (methodName) {
if (!(methodName in obj)) if (!(methodName in obj))
throw 'Method ' + methodName + ' is not defined.'; throw 'Method ' + methodName + ' is not defined.';
obj[methodName].apply(result, args); method = obj[methodName];
} else } else {
obj.apply(result, args); method = obj;
result.constructor = method; }
method.apply(result, args); // 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); stack.push(result);
break; break;
case 0x40: // ActionNewObject case 0x40: // ActionNewObject
@ -689,7 +853,7 @@ function interpretActions(actionsData, scopeContainer,
break; break;
case 0x45: // ActionTargetPath case 0x45: // ActionTargetPath
var obj = stack.pop(); var obj = stack.pop();
stack.push(isMovieClip(obj) ? obj.getTargetPath() : void(0)); stack.push(as2GetType(obj) === 'movieclip' ? obj._target : void(0));
break; break;
case 0x94: // ActionWith case 0x94: // ActionWith
var codeSize = stream.readUI16(); var codeSize = stream.readUI16();
@ -698,68 +862,73 @@ function interpretActions(actionsData, scopeContainer,
processWith(obj, stream.readBytes(codeSize)); processWith(obj, stream.readBytes(codeSize));
break; break;
case 0x4A: // ActionToNumber case 0x4A: // ActionToNumber
stack.push(+stack.pop()); stack.push(as2ToNumber(stack.pop()));
break; break;
case 0x4B: // ActionToString case 0x4B: // ActionToString
stack.push("" + stack.pop()); stack.push(as2ToString(stack.pop()));
break; break;
case 0x44: // ActionTypeOf case 0x44: // ActionTypeOf
var obj = stack.pop(); var obj = stack.pop();
var result = isMovieClip(obj) ? 'movieclip' : typeof obj; var result = as2GetType(obj);
stack.push(result); stack.push(result);
break; break;
case 0x47: // ActionAdd2 case 0x47: // ActionAdd2
var arg1 = stack.pop(); var arg1 = stack.pop();
var arg2 = 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; break;
case 0x48: // ActionLess2 case 0x48: // ActionLess2
var arg1 = stack.pop(); var arg1 = stack.pop();
var arg2 = stack.pop(); var arg2 = stack.pop();
stack.push(arg2 < arg1); stack.push(as2Compare(arg2, arg1));
break; break;
case 0x3F: // ActionModulo case 0x3F: // ActionModulo
var arg1 = stack.pop(); var arg1 = as2ToNumber(stack.pop());
var arg2 = stack.pop(); var arg2 = as2ToNumber(stack.pop());
stack.push(arg2 % arg1); stack.push(arg2 % arg1);
break; break;
case 0x60: // ActionBitAnd case 0x60: // ActionBitAnd
var arg1 = stack.pop(); var arg1 = as2ToInt32(stack.pop());
var arg2 = stack.pop(); var arg2 = as2ToInt32(stack.pop());
stack.push(arg2 & arg1); stack.push(arg2 & arg1);
break; break;
case 0x63: // ActionBitLShift case 0x63: // ActionBitLShift
var arg1 = stack.pop(); var arg1 = as2ToInt32(stack.pop());
var arg2 = stack.pop(); var arg2 = as2ToInt32(stack.pop());
stack.push(arg2 << arg1); stack.push(arg2 << arg1);
break; break;
case 0x61: // ActionBitOr case 0x61: // ActionBitOr
var arg1 = stack.pop(); var arg1 = as2ToInt32(stack.pop());
var arg2 = stack.pop(); var arg2 = as2ToInt32(stack.pop());
stack.push(arg2 | arg1); stack.push(arg2 | arg1);
break; break;
case 0x64: // ActionBitRShift case 0x64: // ActionBitRShift
var arg1 = stack.pop(); var arg1 = as2ToInt32(stack.pop());
var arg2 = stack.pop(); var arg2 = as2ToInt32(stack.pop());
stack.push(arg2 >> arg1); stack.push(arg2 >> arg1);
break; break;
case 0x65: // ActionBitURShift case 0x65: // ActionBitURShift
var arg1 = stack.pop(); var arg1 = as2ToInt32(stack.pop());
var arg2 = stack.pop(); var arg2 = as2ToInt32(stack.pop());
stack.push(arg2 >>> arg1); stack.push(arg2 >>> arg1);
break; break;
case 0x62: // ActionBitXor case 0x62: // ActionBitXor
var arg1 = stack.pop(); var arg1 = as2ToInt32(stack.pop());
var arg2 = stack.pop(); var arg2 = as2ToInt32(stack.pop());
stack.push(arg2 ^ arg1); stack.push(arg2 ^ arg1);
break; break;
case 0x51: // ActionDecrement case 0x51: // ActionDecrement
var arg1 = stack.pop(); var arg1 = as2ToNumber(stack.pop());
arg1--; arg1--;
stack.push(arg1); stack.push(arg1);
break; break;
case 0x50: // ActionIncrement case 0x50: // ActionIncrement
var arg1 = stack.pop(); var arg1 = as2ToNumber(stack.pop());
arg1++; arg1++;
stack.push(arg1); stack.push(arg1);
break; break;
@ -779,7 +948,7 @@ function interpretActions(actionsData, scopeContainer,
case 0x54: // ActionInstanceOf case 0x54: // ActionInstanceOf
var constr = stack.pop(); var constr = stack.pop();
var obj = stack.pop(); var obj = stack.pop();
stack.push(instanceOf(Object(obj), constr)); stack.push(as2InstanceOf(Object(obj), constr));
break; break;
case 0x55: // ActionEnumerate2 case 0x55: // ActionEnumerate2
var obj = stack.pop(); var obj = stack.pop();
@ -795,11 +964,11 @@ function interpretActions(actionsData, scopeContainer,
case 0x67: // ActionGreater case 0x67: // ActionGreater
var arg1 = stack.pop(); var arg1 = stack.pop();
var arg2 = stack.pop(); var arg2 = stack.pop();
stack.push(arg2 > arg1); stack.push(as2Compare(arg1, arg2));
break; break;
case 0x68: // ActionStringGreater case 0x68: // ActionStringGreater
var sa = '' + stack.pop(); var sa = as2ToString(stack.pop());
var sb = '' + stack.pop(); var sb = as2ToString(stack.pop());
var f = sb > sa; var f = sb > sa;
stack.push(isSwfVersion5 ? f : f ? 1 : 0); stack.push(isSwfVersion5 ? f : f ? 1 : 0);
break; break;
@ -859,7 +1028,7 @@ function interpretActions(actionsData, scopeContainer,
case 0x2B: // ActionCastOp case 0x2B: // ActionCastOp
var obj = stack.pop(); var obj = stack.pop();
var constr = stack.pop(); var constr = stack.pop();
stack.push(instanceOf(obj, constr) ? obj : null); stack.push(as2InstanceOf(obj, constr) ? obj : null);
break; break;
case 0x2C: // ActionImplementsOp case 0x2C: // ActionImplementsOp
var constr = stack.pop(); 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'); 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'); var expect = require('expect.js');
require('./domstubs.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'); var expect = require('expect.js');
require('./domstubs.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'); var expect = require('expect.js');
require('./domstubs.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'); var expect = require('expect.js');
require('../stream.js'); require('../stream.js');

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

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

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

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

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

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

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

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

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

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

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

@ -242,8 +242,8 @@ var SourceTracer = (function () {
SourceTracer.prototype = { SourceTracer.prototype = {
traceTraits: function traceTraits(traits, isStatic, inInterfaceNamespace) { traceTraits: function traceTraits(traits, isStatic, inInterfaceNamespace) {
const writer = this.writer; var writer = this.writer;
const tracer = this; var tracer = this;
traits.forEach(function (trait) { traits.forEach(function (trait) {
var str; var str;
@ -316,7 +316,7 @@ var SourceTracer = (function () {
}, },
traceClassStub2: function traceClassStub(trait) { traceClassStub2: function traceClassStub(trait) {
const writer = this.writer; var writer = this.writer;
var ci = trait.classInfo; var ci = trait.classInfo;
var ii = ci.instanceInfo; var ii = ci.instanceInfo;
@ -379,7 +379,7 @@ var SourceTracer = (function () {
}, },
traceClassStub: function traceClassStub(trait) { traceClassStub: function traceClassStub(trait) {
const writer = this.writer; var writer = this.writer;
var ci = trait.classInfo; var ci = trait.classInfo;
var ii = ci.instanceInfo; var ii = ci.instanceInfo;
@ -486,7 +486,7 @@ var SourceTracer = (function () {
}, },
traceClass: function traceClass(ci) { traceClass: function traceClass(ci) {
const writer = this.writer; var writer = this.writer;
var ii = ci.instanceInfo; var ii = ci.instanceInfo;
var name = ii.name; var name = ii.name;
@ -521,7 +521,7 @@ var SourceTracer = (function () {
}, },
traceMetadata: function traceMetadata(metadata) { traceMetadata: function traceMetadata(metadata) {
const writer = this.writer; var writer = this.writer;
for (var key in metadata) { for (var key in metadata) {
if (metadata.hasOwnProperty(key)) { 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 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")); var traceDomain = domainOptions.register(new Option("tdpa", "traceDomain", "boolean", false, "trace domain property access"));
const EXECUTION_MODE = { var EXECUTION_MODE = {
INTERPRET: 0x1, INTERPRET: 0x1,
COMPILE: 0x2 COMPILE: 0x2
}; };
@ -44,12 +44,17 @@ var Domain = (function () {
} else { } else {
this.system = this; this.system = this;
var OWN_INITIALIZE = 0x1;
var SUPER_INITIALIZE = 0x2;
var Class = this.Class = function Class(name, instance, callable) { var Class = this.Class = function Class(name, instance, callable) {
this.debugName = name; this.debugName = name;
if (instance) { if (instance) {
release || assert(instance.prototype); release || assert(instance.prototype);
this.instance = instance; this.instance = instance;
this.instanceNoInitialize = instance;
this.hasInitialize = 0;
} }
if (!callable) { if (!callable) {
@ -77,12 +82,12 @@ var Domain = (function () {
var c = this; var c = this;
var initializes = []; var initializes = [];
while (c) { while (c) {
var s = c.instance.prototype.initialize; if (c.hasInitialize & OWN_INITIALIZE) {
if (s) { initializes.push(c.instance.prototype.initialize);
initializes.push(s);
} }
c = c.baseClass; c = c.baseClass;
} }
var s;
while (s = initializes.pop()) { while (s = initializes.pop()) {
s.call(obj); s.call(obj);
} }
@ -129,6 +134,15 @@ var Domain = (function () {
extend: function (baseClass) { extend: function (baseClass) {
this.baseClass = baseClass; this.baseClass = baseClass;
this.dynamicPrototype = Object.create(baseClass.dynamicPrototype); 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); this.instance.prototype = Object.create(this.dynamicPrototype);
defineNonEnumerableProperty(this.dynamicPrototype, "public$constructor", this); defineNonEnumerableProperty(this.dynamicPrototype, "public$constructor", this);
defineReadOnlyProperty(this.instance.prototype, "class", 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 proto = this.dynamicPrototype;
var keys = Object.keys(definition); var keys = Object.keys(definition);
for (var i = 0, j = keys.length; i < j; i++) { 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."}, OutOfMemoryError : {code: 1000, message: "The system is out of memory."},
NotImplementedError : {code: 1001, message: "The method %1 is not implemented."}, 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."}, 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."}, NullPointerError : {code: 2007, message: "Parameter %1 must be non-null."},
InvalidEnumError : {code: 2008, message: "Parameter %1 must be one of the accepted values."}, InvalidEnumError : {code: 2008, message: "Parameter %1 must be one of the accepted values."},
CantInstantiateError : {code: 2012, message: "%1 class cannot be instantiated."}, CantInstantiateError : {code: 2012, message: "%1 class cannot be instantiated."},
ArgumentError : {code: 2015, message: "Invalid BitmapData."},
EOFError : {code: 2030, message: "End of file was encountered."}, EOFError : {code: 2030, message: "End of file was encountered."},
CompressedDataError : {code: 2058, message: "There was an error decompressing the data."}, CompressedDataError : {code: 2058, message: "There was an error decompressing the data."},
EmptyStringError : {code: 2085, message: "Parameter %1 must be non-empty string."}, EmptyStringError : {code: 2085, message: "Parameter %1 must be non-empty string."},

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

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

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

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

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

@ -136,10 +136,10 @@ function parseTraits(abc, stream, holder) {
var Trait = (function () { var Trait = (function () {
function trait(abc, stream, holder) { function trait(abc, stream, holder) {
const constantPool = abc.constantPool; var constantPool = abc.constantPool;
const methods = abc.methods; var methods = abc.methods;
const classes = abc.classes; var classes = abc.classes;
const metadata = abc.metadata; var metadata = abc.metadata;
this.holder = holder; this.holder = holder;
this.name = constantPool.multinames[stream.readU30()]; 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 * According to Tamarin, this is 0xe000 + 660, with 660 being an "odd legacy
* wart". * wart".
*/ */
const MIN_API_MARK = 0xe294; var MIN_API_MARK = 0xe294;
const MAX_API_MARK = 0xf8ff; var MAX_API_MARK = 0xf8ff;
function namespace(kind, uri) { function namespace(kind, uri) {
if (kind !== undefined) { if (kind !== undefined) {
@ -435,9 +435,9 @@ var Namespace = (function () {
*/ */
var Multiname = (function () { var Multiname = (function () {
const ATTRIBUTE = 0x01; var ATTRIBUTE = 0x01;
const RUNTIME_NAMESPACE = 0x02; var RUNTIME_NAMESPACE = 0x02;
const RUNTIME_NAME = 0x04; var RUNTIME_NAME = 0x04;
var nextID = 1; var nextID = 1;
function multiname(namespaces, name, flags) { function multiname(namespaces, name, flags) {
this.id = nextID ++; this.id = nextID ++;
@ -871,7 +871,7 @@ var MethodInfo = (function () {
} }
function methodInfo(abc, stream) { function methodInfo(abc, stream) {
const constantPool = abc.constantPool; var constantPool = abc.constantPool;
var parameterCount = stream.readU30(); var parameterCount = stream.readU30();
var returnType = constantPool.multinames[stream.readU30()]; var returnType = constantPool.multinames[stream.readU30()];
@ -932,7 +932,7 @@ var MethodInfo = (function () {
}; };
function parseException(abc, stream) { function parseException(abc, stream) {
const multinames = abc.constantPool.multinames; var multinames = abc.constantPool.multinames;
var ex = { var ex = {
start: stream.readU30(), start: stream.readU30(),
@ -947,8 +947,8 @@ var MethodInfo = (function () {
} }
methodInfo.parseBody = function parseBody(abc, stream) { methodInfo.parseBody = function parseBody(abc, stream) {
const constantPool = abc.constantPool; var constantPool = abc.constantPool;
const methods = abc.methods; var methods = abc.methods;
var info = methods[stream.readU30()]; var info = methods[stream.readU30()];
release || assert(!info.isNative()); release || assert(!info.isNative());
@ -976,7 +976,7 @@ var MethodInfo = (function () {
var MetaDataInfo = (function () { var MetaDataInfo = (function () {
function metaDataInfo(abc, stream) { function metaDataInfo(abc, stream) {
const strings = abc.constantPool.strings; var strings = abc.constantPool.strings;
this.tagName = strings[stream.readU30()]; this.tagName = strings[stream.readU30()];
var itemCount = stream.readU30(); var itemCount = stream.readU30();
@ -1021,8 +1021,8 @@ var InstanceInfo = (function () {
var nextID = 1; var nextID = 1;
function instanceInfo(abc, stream) { function instanceInfo(abc, stream) {
this.id = nextID ++; this.id = nextID ++;
const constantPool = abc.constantPool; var constantPool = abc.constantPool;
const methods = abc.methods; var methods = abc.methods;
this.name = constantPool.multinames[stream.readU30()]; this.name = constantPool.multinames[stream.readU30()];
release || assert(Multiname.isQName(this.name)); 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 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")); 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"; var VM_SLOTS = "vm slots";
const VM_LENGTH = "vm length"; var VM_LENGTH = "vm length";
const VM_BINDINGS = "vm bindings"; var VM_BINDINGS = "vm bindings";
const VM_NATIVE_PROTOTYPE_FLAG = "vm native prototype"; var VM_NATIVE_PROTOTYPE_FLAG = "vm native prototype";
const VM_ENUMERATION_KEYS = "vm enumeration keys"; var VM_ENUMERATION_KEYS = "vm enumeration keys";
const VM_OPEN_METHODS = "vm open methods"; var VM_OPEN_METHODS = "vm open methods";
const VM_NEXT_NAME = "vm next name"; var VM_NEXT_NAME = "vm next name";
const VM_NEXT_NAME_INDEX = "vm next name index"; var VM_NEXT_NAME_INDEX = "vm next name index";
const VM_UNSAFE_CLASSES = ["Shumway"]; 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 = [ var VM_NATIVE_BUILTIN_SURROGATES = [
{ object: Object, methods: ["toString", "valueOf"] }, { object: Object, methods: ["toString", "valueOf"] },
{ object: Function, methods: ["toString", "valueOf"] } { object: Function, methods: ["toString", "valueOf"] }
]; ];
const VM_NATIVE_BUILTIN_ORIGINALS = "vm originals"; var VM_NATIVE_BUILTIN_ORIGINALS = "vm originals";
var $M = []; var $M = [];
function initializeGlobalObject(global) { function initializeGlobalObject(global) {
const PUBLIC_MANGLED = /^public\$/; var PUBLIC_MANGLED = /^public\$/;
function getEnumerationKeys(obj) { function getEnumerationKeys(obj) {
var keys = []; var keys = [];
@ -161,7 +161,7 @@ function coerce(value, type) {
return type.coerce(value); return type.coerce(value);
} }
if (isNullOrUndefiend(value)) { if (isNullOrUndefined(value)) {
return null; return null;
} }
@ -787,11 +787,11 @@ var Runtime = (function () {
* compiler bakes it in as a constant which should be much more efficient. * compiler bakes it in as a constant which should be much more efficient.
*/ */
runtime.prototype.createFunction = function createFunction(methodInfo, scope, hasDynamicScope) { 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); release || assert(!mi.isNative(), "Method should have a builtin: ", mi.name);
var hasDefaults = false; var hasDefaults = false;
const defaults = mi.parameters.map(function (p) { var defaults = mi.parameters.map(function (p) {
if (p.value !== undefined) { if (p.value !== undefined) {
hasDefaults = true; hasDefaults = true;
} }
@ -814,7 +814,7 @@ var Runtime = (function () {
return fn; return fn;
} }
const mode = this.domain.mode; var mode = this.domain.mode;
// We use not having an analysis to mean "not initialized". // We use not having an analysis to mean "not initialized".
if (!mi.analysis) { if (!mi.analysis) {
@ -955,7 +955,7 @@ var Runtime = (function () {
return this.createInterface(classInfo); return this.createInterface(classInfo);
} }
const domain = this.domain; var domain = this.domain;
var className = Multiname.getName(ii.name); var className = Multiname.getName(ii.name);
if (traceExecution.value) { if (traceExecution.value) {
@ -1011,7 +1011,7 @@ var Runtime = (function () {
cls.scope = scope; cls.scope = scope;
scope.object = cls; scope.object = cls;
cls.extend(baseClass); 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); 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) { runtime.prototype.applyTraits = function applyTraits(obj, scope, base, traits, classNatives, delayBinding) {
const runtime = this; var runtime = this;
const domain = this.domain; var domain = this.domain;
function makeClosure(trait) { function makeClosure(trait) {
release || assert(scope); release || assert(scope);
@ -1246,7 +1246,7 @@ var Runtime = (function () {
} else if (trait.isMethod()) { } else if (trait.isMethod()) {
// FIXME: Breaking compat with AS and using .bind here instead of the // FIXME: Breaking compat with AS and using .bind here instead of the
// MethodClosure class to work around a SpiderMonkey bug 771871. // MethodClosure class to work around a SpiderMonkey bug 771871.
const MethodClosureClass = domain.system.MethodClosureClass; var MethodClosureClass = domain.system.MethodClosureClass;
var closure; var closure;

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

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

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

@ -82,7 +82,7 @@ function defineNonEnumerableProperty(obj, name, value) {
enumerable: false }); enumerable: false });
} }
function isNullOrUndefiend(value) { function isNullOrUndefined(value) {
return value === null || value === undefined; return value === null || value === undefined;
} }
@ -269,7 +269,7 @@ function utf8decode(str) {
function utf8encode(bytes) { function utf8encode(bytes) {
var str = ""; var str = "";
const fcc = String.fromCharCode; var fcc = String.fromCharCode;
for (var i = 0, j = bytes.length; i < j; i++) { for (var i = 0, j = bytes.length; i < j; i++) {
var b = bytes[i]; var b = bytes[i];
str += b <= 0x7f ? b === 0x25 ? "%25" : fcc(b) : "%" + b.toString(16).toUpperCase(); 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. * If the set fits in a single word, a single int is used.
*/ */
function BitSetFunctor(length) { function BitSetFunctor(length) {
const ADDRESS_BITS_PER_WORD = 5; var ADDRESS_BITS_PER_WORD = 5;
const BITS_PER_WORD = 1 << ADDRESS_BITS_PER_WORD; var BITS_PER_WORD = 1 << ADDRESS_BITS_PER_WORD;
const BIT_INDEX_MASK = BITS_PER_WORD - 1; var BIT_INDEX_MASK = BITS_PER_WORD - 1;
const SIZE = ((length + (BITS_PER_WORD - 1)) >> ADDRESS_BITS_PER_WORD) << ADDRESS_BITS_PER_WORD; var SIZE = ((length + (BITS_PER_WORD - 1)) >> ADDRESS_BITS_PER_WORD) << ADDRESS_BITS_PER_WORD;
function BitSet() { function BitSet() {
/* How many bits are set. */ /* 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 = { var BitmapDataDefinition = (function () {
__class__: 'flash.display.BitmapData' 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_ADD = 'add';
var BLEND_MODE_ALPHA = 'alpha'; var BLEND_MODE_ALPHA = 'alpha';
var BLEND_MODE_DARKEN = 'darken'; var BLEND_MODE_DARKEN = 'darken';
@ -21,18 +21,26 @@ const DisplayObjectDefinition = (function () {
initialize: function () { initialize: function () {
this._alpha = 1; this._alpha = 1;
this._animated = false; this._animated = false;
this._cacheAsBitmap = false;
this._control = document.createElement('div');
this._bbox = null; 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._cxform = null;
this._dirtyArea = null;
this._graphics = null; this._graphics = null;
this._loaderInfo = null; this._loaderInfo = null;
this._mouseChildren = true;
this._mouseOver = false;
this._mouseX = 0; this._mouseX = 0;
this._mouseY = 0; this._mouseY = 0;
this._name = null; this._name = null;
this._opaqueBackground = null; this._opaqueBackground = null;
this._owned = false; this._owned = false;
this._parent = null; this._parent = null;
this._revision = 0;
this._root = null; this._root = null;
this._rotation = 0; this._rotation = 0;
this._scaleX = 1; this._scaleX = 1;
@ -42,12 +50,139 @@ const DisplayObjectDefinition = (function () {
this._visible = true; this._visible = true;
this._x = 0; this._x = 0;
this._y = 0; this._y = 0;
this._updateTransformMatrix();
var s = this.symbol; var s = this.symbol;
if (s) { if (s) {
this._bbox = s.bbox || null; 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() { get accessibilityProperties() {
@ -81,83 +216,6 @@ const DisplayObjectDefinition = (function () {
set filters(val) { set filters(val) {
notImplemented(); 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() { get height() {
var bounds = this.getBounds(); var bounds = this.getBounds();
return bounds.height; return bounds.height;
@ -165,30 +223,9 @@ const DisplayObjectDefinition = (function () {
set height(val) { set height(val) {
notImplemented(); 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() { get loaderInfo() {
return this._loaderInfo || (this._parent ? this._parent.loaderInfo : null); 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() { get mask() {
return null; return null;
}, },
@ -217,15 +254,18 @@ const DisplayObjectDefinition = (function () {
return this._parent; return this._parent;
}, },
get root() { get root() {
return this._root || (this._parent ? this._parent._root : null); return this._root || (this._parent ? this._parent.root : null);
}, },
get rotation() { get rotation() {
return this._rotation; return this._rotation;
}, },
set rotation(val) { set rotation(val) {
this._markAsDirty();
this._rotation = val; this._rotation = val;
this._updateTransformMatrix();
this._slave = false; this._slave = false;
this._updateCurrentTransform();
}, },
get stage() { get stage() {
return this._stage || (this._parent ? this._parent.stage : null); return this._stage || (this._parent ? this._parent.stage : null);
@ -234,17 +274,23 @@ const DisplayObjectDefinition = (function () {
return this._scaleX; return this._scaleX;
}, },
set scaleX(val) { set scaleX(val) {
this._markAsDirty();
this._scaleX = val; this._scaleX = val;
this._updateTransformMatrix();
this._slave = false; this._slave = false;
this._updateCurrentTransform();
}, },
get scaleY() { get scaleY() {
return this._scaleY; return this._scaleY;
}, },
set scaleY(val) { set scaleY(val) {
this._markAsDirty();
this._scaleY = val; this._scaleY = val;
this._updateTransformMatrix();
this._slave = false; this._slave = false;
this._updateCurrentTransform();
}, },
get scale9Grid() { get scale9Grid() {
return null; return null;
@ -262,45 +308,152 @@ const DisplayObjectDefinition = (function () {
return this._transform || new flash.geom.Transform(this); return this._transform || new flash.geom.Transform(this);
}, },
set transform(val) { set transform(val) {
this._currentTransform = val.matrix;
this._slave = false;
var transform = this._transform; var transform = this._transform;
transform.colorTransform = val.colorTransform; transform.colorTransform = val.colorTransform;
transform.matrix = val.matrix; transform.matrix = val.matrix;
this._currentTransformMatrix = val.matrix;
this._slave = false; this._markAsDirty();
}, },
get visible() { get visible() {
return this._visible; return this._visible;
}, },
set visible(val) { set visible(val) {
this._visible = val;
this._slave = false; this._slave = false;
this._visible = val;
this._markAsDirty();
}, },
get width() { get width() {
var bounds = this.getBounds(); var bounds = this.getBounds();
return bounds.width; return bounds.width;
}, },
set width(val) { set width(val) {
//notImplemented(); notImplemented();
}, },
get x() { get x() {
return this._x; return this._x;
}, },
set x(val) { set x(val) {
this._x = val; this._markAsDirty();
this._updateTransformMatrix();
this._slave = false; this._slave = false;
this._x = val;
this._updateCurrentTransform();
}, },
get y() { get y() {
return this._y; return this._y;
}, },
set y(val) { set y(val) {
this._y = val; this._markAsDirty();
this._updateTransformMatrix();
this._slave = false; 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__ = { def.__glue__ = {
native: { native: {

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

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

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

@ -1,4 +1,4 @@
const GraphicsDefinition = (function () { var GraphicsDefinition = (function () {
var GRAPHICS_PATH_COMMAND_CUBIC_CURVE_TO = 6; var GRAPHICS_PATH_COMMAND_CUBIC_CURVE_TO = 6;
var GRAPHICS_PATH_COMMAND_CURVE_TO = 3; var GRAPHICS_PATH_COMMAND_CURVE_TO = 3;
var GRAPHICS_PATH_COMMAND_LINE_TO = 2; var GRAPHICS_PATH_COMMAND_LINE_TO = 2;
@ -25,42 +25,13 @@ const GraphicsDefinition = (function () {
this._drawingStyles = null; this._drawingStyles = null;
this._fillStyle = null; this._fillStyle = null;
this._fillTransform = null; this._fillTransform = null;
this._revision = 0;
this._scale = 1; this._scale = 1;
this._strokeStyle = null; this._strokeStyle = null;
this._subpaths = []; this._subpaths = [];
}, },
beginFill: function (color, alpha) { _beginFillObject: function (fill) {
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) {
if (fill === null) { if (fill === null) {
this.endFill(); this.endFill();
} else { } else {
@ -92,7 +63,7 @@ const GraphicsDefinition = (function () {
} }
} }
}, },
beginStrokeObject: function (istroke) { _beginStrokeObject: function (istroke) {
var stroke = null; var stroke = null;
var fill = 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 () { clear: function () {
delete this._currentPath; delete this._currentPath;
@ -162,19 +191,21 @@ const GraphicsDefinition = (function () {
}, },
cubicCurveTo: function (cp1x, cp1y, cp2x, cp2y, x, y) { cubicCurveTo: function (cp1x, cp1y, cp2x, cp2y, x, y) {
this._currentPath.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); this._currentPath.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
this._revision++;
}, },
curveTo: function (cpx, cpy, x, y) { curveTo: function (cpx, cpy, x, y) {
this._currentPath.quadraticCurveTo(cpx, cpy, x, y); this._currentPath.quadraticCurveTo(cpx, cpy, x, y);
this._revision++;
}, },
drawGraphicsData: function (graphicsData) { drawGraphicsData: function (graphicsData) {
for (var i = 0, n = graphicsData.length; i < n; i++) { for (var i = 0, n = graphicsData.length; i < n; i++) {
var item = graphicsData[i]; var item = graphicsData[i];
if (item.__isIGraphicsPath__) if (item.__isIGraphicsPath__)
this.drawPathObject(item); this._drawPathObject(item);
else if (item.__isIGraphicsFill__) else if (item.__isIGraphicsFill__)
this.beginFillObject(item); this._beginFillObject(item);
else if (item.__isIGraphicsStroke__) else if (item.__isIGraphicsStroke__)
this.beginStrokeObject(item); this._beginStrokeObject(item);
} }
}, },
drawPath: function (commands, data, winding) { 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) { drawRect: function (x, y, w, h) {
if (isNaN(w + h)) if (isNaN(w + h))
throw ArgumentError(); throw ArgumentError();
this._currentPath.rect(x, y, w, h); this._currentPath.rect(x, y, w, h);
this._revision++;
}, },
drawRoundRect: function (x, y, w, h, ellipseWidth, ellipseHeight) { drawRoundRect: function (x, y, w, h, ellipseWidth, ellipseHeight) {
if (isNaN(w + h + ellipseWidth) || (ellipseHeight !== undefined && isNaN(ellipseHeight))) if (isNaN(w + h + ellipseWidth) || (ellipseHeight !== undefined && isNaN(ellipseHeight)))
throw ArgumentError(); 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) { 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(); 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) { drawTriangles: function (vertices, indices, uvtData, culling) {
notImplemented(); notImplemented();
@ -255,7 +301,7 @@ const GraphicsDefinition = (function () {
lineCap: cap || 'round', lineCap: cap || 'round',
lineJoin: cap || 'round', lineJoin: cap || 'round',
lineWidth: width, lineWidth: width,
miterLimit: mlimit miterLimit: mlimit * 2
}; };
this._strokeStyle = toRgba(color, alpha); this._strokeStyle = toRgba(color, alpha);
} else { } else {
@ -263,26 +309,445 @@ const GraphicsDefinition = (function () {
this._strokeStyle = null; this._strokeStyle = null;
} }
}, },
moveTo: function (x, y) {
this._currentPath.moveTo(x, y);
},
lineTo: function (x, y) { lineTo: function (x, y) {
this._currentPath.lineTo(x, y); this._currentPath.lineTo(x, y);
this._revision++;
}, },
moveTo: function (x, y) {
get _currentPath() { this._currentPath.moveTo(x, y);
var path = new Kanvas.Path; this._revision++;
path.drawingStyles = this._drawingStyles; },
path.fillStyle = this._fillStyle; _getBounds: function (includeStroke) {
path.fillTransform = this._fillTransform; var subpaths = this._subpaths;
path.strokeStyle = this._strokeStyle; var xMins = [], yMins = [], xMaxs = [], yMaxs = [];
this._subpaths.push(path); for (var i = 0, n = subpaths.length; i < n; i++) {
// Cache as an own property. var pathTracker = subpaths[i];
Object.defineProperty(this, '_currentPath', describeProperty(path)); var b = pathTracker.getBounds();
return path; 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__ = { def.__glue__ = {
native: { native: {
instance: { instance: {

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

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

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

@ -1,7 +1,7 @@
const LoaderDefinition = (function () { var LoaderDefinition = (function () {
const WORKERS_ENABLED = true; var WORKERS_ENABLED = true;
const LOADER_PATH = 'src/flash/display/Loader.js'; var LOADER_PATH = 'flash/display/Loader.js';
const WORKER_SCRIPTS = [ var WORKER_SCRIPTS = [
'../../../lib/DataView.js/DataView.js', '../../../lib/DataView.js/DataView.js',
'../util.js', '../util.js',
@ -33,7 +33,7 @@ const LoaderDefinition = (function () {
var commitData; var commitData;
if (loader) { if (loader) {
commitData = function (data) { commitData = function (data) {
return loader.commitData(data); return loader._commitData(data);
}; };
} else { } else {
commitData = function (data) { commitData = function (data) {
@ -77,21 +77,29 @@ const LoaderDefinition = (function () {
case SWF_TAG_CODE_DEFINE_SHAPE4: case SWF_TAG_CODE_DEFINE_SHAPE4:
symbol = defineShape(swfTag, symbols); symbol = defineShape(swfTag, symbols);
break; break;
case SWF_TAG_CODE_DEFINE_SOUND:
symbol = {
type: 'sound',
id: swfTag.id
};
break;
case SWF_TAG_CODE_DEFINE_SPRITE: case SWF_TAG_CODE_DEFINE_SPRITE:
var depths = { }; var depths = { };
var frame = { type: 'frame' }; var frame = { type: 'frame' };
var frames = []; var frames = [];
var tags = swfTag.tags; var tags = swfTag.tags;
var frameScripts = null;
var frameIndex = 0;
for (var i = 0, n = tags.length; i < n; i++) { for (var i = 0, n = tags.length; i < n; i++) {
var tag = tags[i]; var tag = tags[i];
switch (tag.code) { switch (tag.code) {
//case SWF_TAG_CODE_DO_ACTION: case SWF_TAG_CODE_DO_ACTION:
// var actionBlocks = frame.actionBlocks; if (!frameScripts)
// if (!actionBlocks) frameScripts = [];
// frame.actionBlocks = [tag.actionsData]; frameScripts.push(frameIndex);
// else frameScripts.push(tag.actionsData);
// actionBlocks.push(tag.actionsData); break;
// break; // case SWF_TAG_CODE_DO_INIT_ACTION: ??
case SWF_TAG_CODE_FRAME_LABEL: case SWF_TAG_CODE_FRAME_LABEL:
frame.labelName = tag.name; frame.labelName = tag.name;
break; break;
@ -113,8 +121,8 @@ const LoaderDefinition = (function () {
i++; i++;
repeat++; repeat++;
} }
if (repeat > 1) frameIndex += repeat;
frame.repeat = repeat; frame.repeat = repeat;
frame.depths = depths; frame.depths = depths;
frames.push(frame); frames.push(frame);
depths = { }; depths = { };
@ -126,7 +134,8 @@ const LoaderDefinition = (function () {
type: 'sprite', type: 'sprite',
id: swfTag.id, id: swfTag.id,
frameCount: swfTag.frameCount, frameCount: swfTag.frameCount,
frames: frames frames: frames,
frameScripts: frameScripts
}; };
break; break;
case SWF_TAG_CODE_DEFINE_TEXT: case SWF_TAG_CODE_DEFINE_TEXT:
@ -146,7 +155,6 @@ const LoaderDefinition = (function () {
symbols[swfTag.id] = symbol; symbols[swfTag.id] = symbol;
commitData(symbol); commitData(symbol);
} }
function parseBytes(bytes) { function parseBytes(bytes) {
var depths = { }; var depths = { };
var frame = { type: 'frame' }; var frame = { type: 'frame' };
@ -174,21 +182,20 @@ const LoaderDefinition = (function () {
else else
frame.abcBlocks = [tag.data]; frame.abcBlocks = [tag.data];
break; break;
//case SWF_TAG_CODE_DO_ACTION: case SWF_TAG_CODE_DO_ACTION:
// var actionBlocks = frame.actionBlocks; var actionBlocks = frame.actionBlocks;
// if (actionBlocks) if (actionBlocks)
// actionBlocks.push(tag.actionData); actionBlocks.push(tag.actionsData);
// else else
// frame.actionBlocks = [tag.actionData]; frame.actionBlocks = [tag.actionsData];
// break; break;
//case SWF_TAG_CODE_DO_INIT_ACTION: case SWF_TAG_CODE_DO_INIT_ACTION:
// var initActionBlocks = frame.initActionBlocks; var initActionBlocks = frame.initActionBlocks;
// if (!initActionBlocks) { if (!initActionBlocks) {
// initActionBlocks = { }; frame.initActionBlocks = initActionBlocks = {};
// frame.initActionBlocks = initActionBlocks; }
// } initActionBlocks[tag.spriteId] = tag.actionsData;
// initActionBlocks[tag.spriteId] = tag.actionsData; break;
// break;
case SWF_TAG_CODE_EXPORT_ASSETS: case SWF_TAG_CODE_EXPORT_ASSETS:
case SWF_TAG_CODE_SYMBOL_CLASS: case SWF_TAG_CODE_SYMBOL_CLASS:
var exports = frame.exports; var exports = frame.exports;
@ -221,8 +228,7 @@ const LoaderDefinition = (function () {
tagsProcessed++; tagsProcessed++;
repeat++; repeat++;
} }
if (repeat > 1) frame.repeat = repeat;
frame.repeat = repeat;
frame.depths = depths; frame.depths = depths;
commitData(frame); commitData(frame);
depths = { }; depths = { };
@ -287,28 +293,14 @@ const LoaderDefinition = (function () {
this._timeline = []; this._timeline = [];
}, },
get contentLoaderInfo() { _commitData: function (data) {
// 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) {
var loaderInfo = this.contentLoaderInfo; var loaderInfo = this.contentLoaderInfo;
loaderInfo.dispatchEvent(new flash.events.Event("progress")); loaderInfo.dispatchEvent(new flash.events.Event("progress"));
switch (data.command) { switch (data.command) {
case 'init': case 'init':
this.init(data.result); this._init(data.result);
break; break;
case 'complete': case 'complete':
loaderInfo.dispatchEvent(new flash.events.Event("complete")); loaderInfo.dispatchEvent(new flash.events.Event("complete"));
@ -318,14 +310,16 @@ const LoaderDefinition = (function () {
break; break;
default: default:
if (data.id) if (data.id)
this.commitSymbol(data); this._commitSymbol(data);
else if (data.type === 'frame') else if (data.type === 'frame')
this.commitFrame(data); this._commitFrame(data);
break; break;
} }
}, },
commitFrame: function (frame) { _commitFrame: function (frame) {
var abcBlocks = frame.abcBlocks; var abcBlocks = frame.abcBlocks;
var actionBlocks = frame.actionBlocks;
var initActionBlocks = frame.initActionBlocks;
var depths = frame.depths; var depths = frame.depths;
var exports = frame.exports; var exports = frame.exports;
var loader = this; var loader = this;
@ -353,8 +347,10 @@ const LoaderDefinition = (function () {
if (frame.bgcolor) if (frame.bgcolor)
loaderInfo._backgroundColor = frame.bgcolor; loaderInfo._backgroundColor = frame.bgcolor;
else
loaderInfo._backgroundColor = { color: 0xFFFFFF, alpha: 0xFF };
var i = frame.repeat || 1; var i = frame.repeat;
while (i--) while (i--)
timeline.push(framePromise); 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++) { for (var i = 0, n = exports.length; i < n; i++) {
var asset = exports[i]; var asset = exports[i];
var symbolPromise = dictionary[asset.symbolId]; var symbolPromise = dictionary[asset.symbolId];
@ -387,8 +383,8 @@ const LoaderDefinition = (function () {
} }
var root = loader._content; var root = loader._content;
var needRootObject = !root;
if (!root) { if (needRootObject) {
var stage = loader._stage; var stage = loader._stage;
var rootClass = avm2.applicationDomain.getClass(val.className); var rootClass = avm2.applicationDomain.getClass(val.className);
@ -404,10 +400,15 @@ const LoaderDefinition = (function () {
loader._content = root; loader._content = root;
} }
framePromise.resolve(displayList); if (!loader._isAvm2Enabled) {
root._framesLoaded++; loader._initAvm1Bindings(root, needRootObject, frameNum,
actionBlocks, initActionBlocks, exports);
}
if (labelName) { framePromise.resolve(displayList);
root._framesLoaded += frame.repeat;
if (labelName && root._frameLabels) {
root._frameLabels[labelName] = { root._frameLabels[labelName] = {
__class__: 'flash.display.FrameLabel', __class__: 'flash.display.FrameLabel',
frame: frameNum, frame: frameNum,
@ -419,11 +420,61 @@ const LoaderDefinition = (function () {
loaderInfo.dispatchEvent(new flash.events.Event('init')); 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 dependencies = symbol.require;
var dictionary = this._dictionary; var dictionary = this._dictionary;
var promiseQueue = []; var promiseQueue = [];
var symbolInfo = {}; var symbolInfo = { };
var symbolPromise = new Promise; var symbolPromise = new Promise;
if (dependencies && dependencies.length) { if (dependencies && dependencies.length) {
@ -437,7 +488,37 @@ const LoaderDefinition = (function () {
switch (symbol.type) { switch (symbol.type) {
case 'button': 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.className = 'flash.display.SimpleButton';
symbolInfo.props = {
states: states
};
break; break;
case 'font': case 'font':
var charset = fromCharCode.apply(null, symbol.codes); var charset = fromCharCode.apply(null, symbol.codes);
@ -462,14 +543,20 @@ const LoaderDefinition = (function () {
imgPromise.resolve(); imgPromise.resolve();
}; };
img.src = 'data:' + symbol.mimeType + ';base64,' + btoa(symbol.data); img.src = 'data:' + symbol.mimeType + ';base64,' + btoa(symbol.data);
promiseQueue.push(imgPromise); promiseQueue.push(imgPromise);
symbolInfo.className = 'flash.display.BitmapData'; symbolInfo.className = 'flash.display.BitmapData';
symbolInfo.props = { img: describeProperty(img) }; symbolInfo.props = {
img: img,
width: symbol.width,
height: symbol.height
};
break; break;
case 'label': case 'label':
var drawFn = new Function('d,c,r', symbol.data); var drawFn = new Function('d,c,r', symbol.data);
symbolInfo.className = 'flash.text.StaticText'; symbolInfo.className = 'flash.text.StaticText';
symbolInfo.props = { symbolInfo.props = {
bbox: symbol.bbox,
draw: function (c, r) { draw: function (c, r) {
return drawFn.call(this, dictionary, 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); var drawFn = new Function('d,c,r', symbol.data);
symbolInfo.className = 'flash.text.TextField'; symbolInfo.className = 'flash.text.TextField';
symbolInfo.props = { symbolInfo.props = {
bbox: symbol.bbox,
draw: function (c, r) { draw: function (c, r) {
return drawFn.call(this, dictionary, c, r); return drawFn.call(this, dictionary, c, r);
}, },
text: symbol.value text: symbol.value,
variableName: symbol.variableName
}; };
break; break;
case 'shape': case 'shape':
var bbox = symbol.bbox;
var createGraphicsData = new Function('d,r', 'return ' + symbol.data); var createGraphicsData = new Function('d,r', 'return ' + symbol.data);
var graphics = new flash.display.Graphics; var graphics = new flash.display.Graphics;
graphics._scale = 0.05; graphics._scale = 0.05;
graphics.drawGraphicsData(createGraphicsData(dictionary, 0));
symbolInfo.className = 'flash.display.Shape'; symbolInfo.className = 'flash.display.Shape';
symbolInfo.props = { symbolInfo.props = {
bbox: { bbox: symbol.bbox,
left: bbox.left / 20,
top: bbox.top / 20,
right: bbox.right / 20,
bottom: bbox.bottom / 20
},
graphics: graphics graphics: graphics
}; };
symbolPromise.then(function () {
graphics.drawGraphicsData(createGraphicsData(dictionary, 0));
});
break;
case 'sound':
symbolInfo.className = 'flash.media.Sound';
symbolInfo.props = { };
break; break;
case 'sprite': case 'sprite':
var frameCount = symbol.frameCount; var frameCount = symbol.frameCount;
@ -537,7 +627,7 @@ const LoaderDefinition = (function () {
}; };
} }
var j = frame.repeat || 1; var j = frame.repeat;
while (j--) while (j--)
timeline.push(framePromise); timeline.push(framePromise);
@ -549,6 +639,7 @@ const LoaderDefinition = (function () {
timeline: timeline, timeline: timeline,
framesLoaded: frameCount, framesLoaded: frameCount,
frameLabels: frameLabels, frameLabels: frameLabels,
frameScripts: symbol.frameScripts,
totalFrames: frameCount totalFrames: frameCount
}; };
break; break;
@ -559,30 +650,16 @@ const LoaderDefinition = (function () {
symbolPromise.resolve(symbolInfo); symbolPromise.resolve(symbolInfo);
}); });
}, },
getSymbolInfoByName: function (className) { _init: function (info) {
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) {
var loader = this; var loader = this;
var loaderInfo = loader.contentLoaderInfo; var loaderInfo = loader.contentLoaderInfo;
loaderInfo._swfVersion = info.swfVersion; loaderInfo._swfVersion = info.swfVersion;
var bounds = info.bounds; var bbox = info.bbox;
loaderInfo._width = (bounds.xMax - bounds.xMin) / 20; loaderInfo._width = bbox.right - bbox.left;
loaderInfo._height = (bounds.yMax - bounds.yMin) / 20; loaderInfo._height = bbox.bottom - bbox.top;
loaderInfo._frameRate = info.frameRate; loaderInfo._frameRate = info.frameRate;
@ -600,37 +677,36 @@ const LoaderDefinition = (function () {
loader._vmPromise = vmPromise; loader._vmPromise = vmPromise;
loader._isAvm2Enabled = info.fileAttributes.doAbc; loader._isAvm2Enabled = info.fileAttributes.doAbc;
this.setup(); this._setup();
}, },
load: function (request, context) { _loadFrom: function (input, context) {
this.loadFrom(request.url);
},
loadBytes: function (bytes, context) {
if (!bytes.length)
throw ArgumentError();
this.loadFrom(bytes);
},
loadFrom: function (input, context) {
if (typeof window !== 'undefined' && WORKERS_ENABLED) { if (typeof window !== 'undefined' && WORKERS_ENABLED) {
var loader = this; var loader = this;
var worker = new Worker(SHUMWAY_ROOT + LOADER_PATH); var worker = new Worker(SHUMWAY_ROOT + LOADER_PATH);
worker.onmessage = function (evt) { worker.onmessage = function (evt) {
loader.commitData(evt.data); loader._commitData(evt.data);
}; };
worker.postMessage(input); worker.postMessage(input);
} else { } else {
loadFromWorker(this, input, context); loadFromWorker(this, input, context);
} }
}, },
setup: function () { _setup: function () {
var loader = this; var loader = this;
var stage = loader._stage; var stage = loader._stage;
if (loader._isAvm2Enabled) { 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(); loader._vmPromise.resolve();
} else { } 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); AS2Key.$bind(stage);
AS2Mouse.$bind(stage); AS2Mouse.$bind(stage);
@ -638,6 +714,30 @@ const LoaderDefinition = (function () {
loader._vmPromise.resolve(); 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 () { unload: function () {
notImplemented(); notImplemented();
}, },

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

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

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

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

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

@ -1,4 +1,4 @@
const MovieClipDefinition = (function () { var MovieClipDefinition = (function () {
var def = { var def = {
__class__: 'flash.display.MovieClip', __class__: 'flash.display.MovieClip',
@ -16,7 +16,6 @@ const MovieClipDefinition = (function () {
this._scenes = { }; this._scenes = { };
this._timeline = null; this._timeline = null;
this._totalFrames = 1; this._totalFrames = 1;
this._scenes = { };
var s = this.symbol; var s = this.symbol;
if (s) { if (s) {
@ -27,27 +26,265 @@ const MovieClipDefinition = (function () {
} }
}, },
addFrameScript: function () { _callFrame: function (frameNum) {
// 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) {
if (frameNum in this._frameScripts) { if (frameNum in this._frameScripts) {
var scripts = this._frameScripts[frameNum]; var scripts = this._frameScripts[frameNum];
for (var i = 0, n = scripts.length; i < n; i++) for (var i = 0, n = scripts.length; i < n; i++)
scripts[i].call(this); 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() { get currentFrame() {
return this._currentFrame; return this._currentFrame;
}, },
@ -72,142 +309,48 @@ const MovieClipDefinition = (function () {
get framesLoaded() { get framesLoaded() {
return this._framesLoaded; return this._framesLoaded;
}, },
gotoFrame: function (frameNum, scene) { get totalFrames() {
if (frameNum > this._totalFrames) return this._totalFrames;
frameNum = 1; },
get trackAsMenu() {
return false;
},
set trackAsMenu(val) {
notImplemented();
},
if (frameNum > this.framesLoaded) addFrameScript: function () {
frameNum = this.framesLoaded; // arguments are pairs of frameIndex and script/function
// frameIndex is in range 0..totalFrames-1
if (frameNum === this._currentFrame) { var frameScripts = this._frameScripts;
return; 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];
} }
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;
else
depthMap.splice(-1);
}
} 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) { gotoAndPlay: function (frame, scene) {
this.play(); this.play();
if (isNaN(frame)) if (isNaN(frame))
this.gotoLabel(frame); this.gotoLabel(frame);
else else
this.gotoFrame(frame); this._gotoFrame(frame);
}, },
gotoAndStop: function (frame, scene) { gotoAndStop: function (frame, scene) {
this.stop(); this.stop();
if (isNaN(frame)) if (isNaN(frame))
this.gotoLabel(frame); this.gotoLabel(frame);
else else
this.gotoFrame(frame); this._gotoFrame(frame);
}, },
gotoLabel: function (labelName) { gotoLabel: function (labelName) {
var frameLabel = this._frameLabels[labelName]; var frameLabel = this._frameLabels[labelName];
if (frameLabel) if (frameLabel)
this.gotoFrame(frameLabel.frame); this._gotoFrame(frameLabel.frame);
}, },
isPlaying: function () { isPlaying: function () {
return this._isPlaying; return this._isPlaying;
@ -229,19 +372,10 @@ const MovieClipDefinition = (function () {
}, },
stop: function () { stop: function () {
this._isPlaying = false; 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__ = { def.__glue__ = {
native: { native: {

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

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

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

@ -1,3 +1,131 @@
const SimpleButtonDefinition = { var SimpleButtonDefinition = (function () {
__class__: 'flash.display.SimpleButton' 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 = { var def = {
__class__: 'flash.display.Sprite', __class__: 'flash.display.Sprite',
initialize: function () { initialize: function () {
this._buttonMode = false;
this._useHandCursor = true;
var s = this.symbol; var s = this.symbol;
if (s) { if (s) {
this._graphics = s.graphics || new flash.display.Graphics; 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() { get buttonMode() {
return false; return this._buttonMode;
}, },
set buttonMode(val) { set buttonMode(val) {
notImplemented(); this._buttonMode = val;
}, },
get graphics() { get graphics() {
return this._graphics; return this._graphics;
}, },
get hitArea() { get hitArea() {
return null; return this._hitArea;
}, },
set hitArea(val) { set hitArea(val) {
notImplemented(); this._hitArea = val;
}, },
get soundTransform() { get soundTransform() {
notImplemented(); notImplemented();
@ -32,6 +50,17 @@ const SpriteDefinition = (function () {
set soundTransform(val) { set soundTransform(val) {
notImplemented(); 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) { startDrag: function (lockCenter, bounds) {
notImplemented(); notImplemented();
}, },
@ -43,19 +72,10 @@ const SpriteDefinition = (function () {
}, },
stopTouchDrag: function (touchPointID) { stopTouchDrag: function (touchPointID) {
notImplemented(); notImplemented();
},
get useHandCursor() {
return true;
},
set useHandCursor(val) {
notImplemented();
},
constructChildren: function () {
// notImplemented();
} }
}; };
const desc = Object.getOwnPropertyDescriptor; var desc = Object.getOwnPropertyDescriptor;
def.__glue__ = { def.__glue__ = {
native: { native: {
@ -67,7 +87,7 @@ const SpriteDefinition = (function () {
stopDrag: def.stopDrag, stopDrag: def.stopDrag,
startTouchDrag: def.startTouchDrag, startTouchDrag: def.startTouchDrag,
stopTouchDrag: def.stopTouchDrag, stopTouchDrag: def.stopTouchDrag,
constructChildren: def.constructChildren, constructChildren: def._constructChildren,
hitArea: desc(def, "hitArea"), hitArea: desc(def, "hitArea"),
useHandCursor: desc(def, "useHandCursor"), useHandCursor: desc(def, "useHandCursor"),
soundTransform: desc(def, "soundTransform") soundTransform: desc(def, "soundTransform")
@ -77,4 +97,3 @@ const SpriteDefinition = (function () {
return def; return def;
}).call(this); }).call(this);

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

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

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

@ -1,4 +1,4 @@
const EventDefinition = (function () { var EventDefinition = (function () {
var EVENT_PHASE_CAPTURING_PHASE = 1; var EVENT_PHASE_CAPTURING_PHASE = 1;
var EVENT_PHASE_AT_TARGET = 2; var EVENT_PHASE_AT_TARGET = 2;
var EVENT_PHASE_BUBBLING_PHASE = 3; var EVENT_PHASE_BUBBLING_PHASE = 3;
@ -13,17 +13,21 @@ const EventDefinition = (function () {
this._target = null; this._target = null;
}, },
ctor: function (type, bubbles, cancelable) {
this.type = type;
this.bubbles = !!bubbles;
this.cancelable = !!cancelable;
},
get currentTarget() { get currentTarget() {
return this._currentTarget; return this._currentTarget;
}, },
get eventPhase() { get eventPhase() {
return this._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 () { isDefaultPrevented: function () {
return this._isDefaultPrevented; return this._isDefaultPrevented;
}, },
@ -35,13 +39,10 @@ const EventDefinition = (function () {
}, },
stopPropagation: function () { stopPropagation: function () {
notImplemented(); notImplemented();
}, }
get target() {
return this._target;
},
}; };
const desc = Object.getOwnPropertyDescriptor; var desc = Object.getOwnPropertyDescriptor;
def.__glue__ = { def.__glue__ = {
script: { script: {

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

@ -1,4 +1,4 @@
const EventDispatcherDefinition = (function () { var EventDispatcherDefinition = (function () {
var CUSTOM_DOM_EVENT_PREFIX = 'shumway.'; var CUSTOM_DOM_EVENT_PREFIX = 'shumway.';
var def = { var def = {
@ -13,7 +13,6 @@ const EventDispatcherDefinition = (function () {
ctor: function (target) { ctor: function (target) {
this._target = target; this._target = target;
}, },
addEventListener: function (type, listener, useCapture, prio, useWeakReference) { addEventListener: function (type, listener, useCapture, prio, useWeakReference) {
if (typeof listener !== 'function') if (typeof listener !== 'function')
throw ArgumentError(); throw ArgumentError();
@ -89,12 +88,14 @@ const EventDispatcherDefinition = (function () {
var handlers = useCapture ? this._captureHandlers : this._handlers; var handlers = useCapture ? this._captureHandlers : this._handlers;
var handler = handlers[type]; var handler = handlers[type];
if (handler) { if (handler) {
var listeners = handler.listeners; var queue = handler.queue;
var i = listeners.indexOf(listener); for (var i = 0; i < queue.length; i++) {
if (i > -1) if (queue[i].listener === listener) {
listeners.splice(i, 1); queue.splice(i, 1);
break;
if (!listeners.length) { }
}
if (!queue.length) {
if (this._control) if (this._control)
this._control.removeEventListener(CUSTOM_DOM_EVENT_PREFIX + type, handler, useCapture); this._control.removeEventListener(CUSTOM_DOM_EVENT_PREFIX + type, handler, useCapture);

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

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

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

@ -1,4 +1,4 @@
const MouseEventDefinition = (function () { var MouseEventDefinition = (function () {
var def = { var def = {
__class__: 'flash.events.MouseEvent', __class__: 'flash.events.MouseEvent',
@ -31,7 +31,7 @@ const MouseEventDefinition = (function () {
ROLL_OUT: 'public ROLL_OUT', ROLL_OUT: 'public ROLL_OUT',
ROLL_OVER: 'public ROLL_OVER' ROLL_OVER: 'public ROLL_OVER'
}, },
} },
native: { native: {
instance: { 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 = { var def = {
__class__: 'flash.events.TimerEvent', __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 = { var def = {
__class__: 'flash.geom.ColorTransform', __class__: 'flash.geom.ColorTransform',

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

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

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

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

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

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

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

@ -1,12 +1,7 @@
const TransformDefinition = (function () { var TransformDefinition = (function () {
var def = { var def = {
__class__: 'flash.geom.Transform', __class__: 'flash.geom.Transform',
ctor: function (target) {
this._target = target;
target._transform = this;
},
get colorTransform() { get colorTransform() {
var cxform = this._target._cxform; var cxform = this._target._cxform;
if (cxform) { if (cxform) {
@ -51,34 +46,48 @@ const TransformDefinition = (function () {
return m; return m;
}, },
get matrix() { get matrix() {
var target = this._target; var m = this._target._currentTransform;
var m = new flash.geom.Matrix; return new flash.geom.Matrix(m.a, m.b, m.c, m.d, m.tx, m.ty);
m.createBox(
target._scaleX,
target._scaleY,
target._rotation * Math.PI / 180,
target._x,
target._y
);
return m;
}, },
set matrix(val) { set matrix(val) {
var MatrixClass = avm2.systemDomain.getClass("flash.geom.Matrix"); var MatrixClass = avm2.systemDomain.getClass("flash.geom.Matrix");
if (!MatrixClass.isInstanceOf(val)) if (!MatrixClass.isInstanceOf(val))
throw TypeError(); 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; var target = this._target;
target._rotation = Math.atan2(val.b, val.a) * 180 / Math.PI; target._rotation = Math.atan2(b, a) * 180 / Math.PI;
var sx = Math.sqrt(val.a * val.a + val.b * val.b); var sx = Math.sqrt(a * a + b * b);
target._scaleX = val.a > 0 ? sx : -sx; target._scaleX = a > 0 ? sx : -sx;
var sy = Math.sqrt(val.d * val.d + val.c * val.c); var sy = Math.sqrt(d * d + c * c);
target._scaleY = val.d > 0 ? sy : -sy; target._scaleY = d > 0 ? sy : -sy;
target._x = val.tx; target._x = val.tx;
target._y = val.ty; 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__ = { def.__glue__ = {
native: { 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) { var SoundTransformDefinition = (function () {
EventDispatcher.call(this); var def = {
__class__: 'flash.media.SoundTransform',
};
this.volume = volume; return def;
this.pan = pan || 0; }).call(this);
}
SoundTransform.prototype = Object.create(null, {
__class__: describeInternalProperty('flash.media.SoundTransform'),
_timerDispatch: describeMethod(function () {
})
});

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

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

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

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

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

@ -1,9 +1,21 @@
const NetStreamDefinition = (function () { var NetStreamDefinition = (function () {
var def = { var def = {
ctor: function(connection, peerID) {
// notImplemented();
},
play: function (url) { play: function (url) {
this._url = url; this._url = url;
} }
}; };
def.__glue__ = {
native: {
instance: {
ctor: def.ctor,
play: def.play
}
}
};
return def; return def;
}).call(this); }).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.Sprite", "SpriteClass", SpriteDefinition),
M("flash.display.MovieClip", "MovieClipClass", MovieClipDefinition), M("flash.display.MovieClip", "MovieClipClass", MovieClipDefinition),
M("flash.display.Shape", "ShapeClass", ShapeDefinition), 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.Stage", "StageClass", StageDefinition),
M("flash.display.Loader", "LoaderClass", LoaderDefinition), M("flash.display.Loader", "LoaderClass", LoaderDefinition),
M("flash.display.LoaderInfo", "LoaderInfoClass", LoaderInfoDefinition), M("flash.display.LoaderInfo", "LoaderInfoClass", LoaderInfoDefinition),
M("flash.display.Graphics", "GraphicsClass", GraphicsDefinition), 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.Point", "PointClass", PointDefinition),
M("flash.geom.Rectangle", "RectangleClass", RectangleDefinition), M("flash.geom.Rectangle", "RectangleClass", RectangleDefinition),
@ -113,14 +117,31 @@ var as3error = {};
M("flash.events.EventDispatcher", "EventDispatcherClass", EventDispatcherDefinition), M("flash.events.EventDispatcher", "EventDispatcherClass", EventDispatcherDefinition),
M("flash.events.Event", "EventClass", EventDefinition), M("flash.events.Event", "EventClass", EventDefinition),
M("flash.events.KeyboardEvent", "KeyboardEventClass", KeyboardEventDefinition), M("flash.events.KeyboardEvent", "KeyboardEventClass", KeyboardEventDefinition),
M("flash.events.MouseEvent", "MouseEventClass", MouseEventDefinition),
M("flash.events.TextEvent", "TextEventClass", TextEventDefinition),
M("flash.events.TimerEvent", "TimerEventClass", TimerEventDefinition), M("flash.events.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.TextField", "TextFieldClass", TextFieldDefinition),
M("flash.text.StaticText", "StaticTextClass", StaticTextDefinition), 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) { M("flash.utils.Timer", "TimerClass", TimerDefinition)].forEach(function (m) {
var path = m.className.split("."); var path = m.className.split(".");
@ -136,10 +157,7 @@ var as3error = {};
// Hook up the native. // Hook up the native.
natives[m.nativeName] = function (runtime, scope, instance, baseClass) { natives[m.nativeName] = function (runtime, scope, instance, baseClass) {
var c = new runtime.domain.system.Class(name, function () { var c = new runtime.domain.system.Class(name, instance);
this.class.initializeInstance(this);
instance.apply(this, arguments);
});
c.extend(baseClass); c.extend(baseClass);
c.link(m.definition); c.link(m.definition);
return c; return c;
@ -153,3 +171,19 @@ natives['FlashUtilScript::getTimer'] = function GetTimerMethod(runtime, scope, i
return Date.now() - start; 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 = { var FontDefinition = (function () {
__class__: 'flash.text.Font' 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 = { var def = {
__class__: 'flash.text.StaticText', __class__: 'flash.text.StaticText',
@ -17,7 +17,7 @@ const StaticTextDefinition = (function () {
} }
}; };
const desc = Object.getOwnPropertyDescriptor; var desc = Object.getOwnPropertyDescriptor;
def.__glue__ = { def.__glue__ = {
native: { native: {

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

@ -1,4 +1,4 @@
const TextFieldDefinition = (function () { var TextFieldDefinition = (function () {
var def = { var def = {
__class__: 'flash.text.TextField', __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() { get text() {
return this._text; return this._text;
}, },
set text(val) { set text(val) {
this._text = val; if (this._text !== val) {
this._text = val;
this._markAsDirty();
}
} }
}; };
const desc = Object.getOwnPropertyDescriptor; var desc = Object.getOwnPropertyDescriptor;
def.__glue__ = { def.__glue__ = {
native: { native: {

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

@ -1,11 +1,8 @@
var ShumwayKeyboardListener = { var ShumwayKeyboardListener = {
handleEvent: function (domEvt) { 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) { if (this.focus) {
this.focus.dispatchEvent(new flash.events.KeyboardEvent( this.focus.dispatchEvent(new flash.events.KeyboardEvent(
domEvt.type === 'keyup' ? KEClass.KEY_UP : KEClass.KEY_DOWN, domEvt.type === 'keyup' ? 'keyUp' : 'keyDown',
true, true,
false, false,
domEvt.charCode, domEvt.charCode,
@ -22,7 +19,7 @@ var ShumwayKeyboardListener = {
window.addEventListener('keydown', ShumwayKeyboardListener); window.addEventListener('keydown', ShumwayKeyboardListener);
window.addEventListener('keyup', ShumwayKeyboardListener); window.addEventListener('keyup', ShumwayKeyboardListener);
const KeyboardDefinition = (function () { var KeyboardDefinition = (function () {
var def = { var def = {
get capsLock() { get capsLock() {
return false; // TODO Stage.instance.$keyboard.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__ = { def.__glue__ = {
script: { script: {

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

@ -1,29 +1,51 @@
var Mouse = describePrototype({ var MouseDefinition = (function() {
cursor: describeAccessor(
function () {
return 'auto'; // TODO
},
function (val) {
notImplemented();
}
),
supportsCursor: describeAccessor(function () {
return true; // TODO
}),
supportsNativeCursor: describeAccessor(function () {
return true; // TODO
}),
hide: describeMethod(function () { var def = {
__class__: 'flash.ui.Mouse',
$bind: function(stage) {
this._stage = stage;
},
};
function hide() {
this._stage._setCursorVisible(false);
}
function show() {
this._stage._setCursorVisible(true);
}
function registerCursor() {
notImplemented(); notImplemented();
}), }
registerCursor: describeMethod(function (name, cursor) {
function unregisterCursor() {
notImplemented(); notImplemented();
}), }
show: describeMethod(function () {
notImplemented(); def.__glue__ = {
}), native: {
unregisterCursor: describeMethod(function (name) { static: {
notImplemented(); 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) { function describeProperty(val) {
return { value: val, writable: true, configurable: true, enumerable: true }; return { value: val, writable: true, configurable: true, enumerable: true };
} }
@ -45,7 +20,7 @@ Promise.when = function () {
promise.resolve(); promise.resolve();
} else { } else {
var values = []; var values = [];
for (var i = 0; i < numPromises; i++) { for (var i = 0, n = numPromises; i < n; i++) {
var arg = arguments[i]; var arg = arguments[i];
arg.then(function (val) { arg.then(function (val) {
values.push(val); values.push(val);

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

@ -1,4 +1,4 @@
const TimerDefinition = (function () { var TimerDefinition = (function () {
var def = { var def = {
__class__: 'flash.utils.Timer', __class__: 'flash.utils.Timer',
initialize: function () { 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_COLORMAPPED = 3;
/** @const */ var FORMAT_15BPP = 4; /** @const */ var FORMAT_15BPP = 4;
@ -12,13 +12,13 @@ function rgbToString(bytes, pos) {
return fromCharCode(red, green, blue); return fromCharCode(red, green, blue);
} }
function argbToString(bytes, pos) { function argbToString(bytes, pos) {
var alpha = bytes[pos]; var alpha = bytes[pos] / 0xff;
if (!alpha) if (!alpha)
return '\x00\x00\x00\x00'; return '\x00\x00\x00\x00';
// RGB values are alpha pre-multiplied (per SWF spec). // RGB values are alpha pre-multiplied (per SWF spec).
var red = 0 | ((bytes[pos + 1] * 255) / alpha); var red = 0 | (bytes[pos + 1] / alpha);
var green = 0 | ((bytes[pos + 2] * 255) / alpha); var green = 0 | (bytes[pos + 2] / alpha);
var blue = 0 | ((bytes[pos + 3] * 255) / alpha); var blue = 0 | (bytes[pos + 3] / alpha);
return fromCharCode(red, green, blue, alpha); return fromCharCode(red, green, blue, alpha);
} }
@ -161,6 +161,8 @@ function defineBitmap(tag) {
return { return {
type: 'image', type: 'image',
id: tag.id, id: tag.id,
width: width,
height: height,
mimeType: 'image/png', mimeType: 'image/png',
data: data 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) { function defineButton(tag, dictionary) {
var characters = tag.characters; var characters = tag.characters;
var dependencies = [];
var states = { var states = {
up: {type: 'pframe'}, up: {},
over: {type: 'pframe'}, over: {},
down: {type: 'pframe'}, down: {},
hitTest: {type: 'pframe'} hitTest: {}
}; };
var i = 0; var i = 0;
while (character = characters[i++]) { while (character = characters[i++]) {
@ -16,7 +15,7 @@ function defineButton(tag, dictionary) {
var characterItem = dictionary[character.characterId]; var characterItem = dictionary[character.characterId];
assert(characterItem, 'undefined character', 'button'); assert(characterItem, 'undefined character', 'button');
var entry = { var entry = {
id: characterItem.id, symbolId: characterItem.id,
matrix: character.matrix matrix: character.matrix
}; };
if (character.stateUp) if (character.stateUp)
@ -27,7 +26,6 @@ function defineButton(tag, dictionary) {
states.down[character.depth] = entry; states.down[character.depth] = entry;
if (character.stateHitTest) if (character.stateHitTest)
states.hitTest[character.depth] = entry; states.hitTest[character.depth] = entry;
dependencies.push(characterItem.id);
} }
var button = { var button = {
type: 'button', type: 'button',
@ -35,7 +33,5 @@ function defineButton(tag, dictionary) {
buttonActions: tag.buttonActions, buttonActions: tag.buttonActions,
states: states states: states
}; };
if (dependencies.length)
button.require = dependencies;
return button; return button;
} }

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

@ -5,12 +5,32 @@ SWF.embed = function(file, container, options) {
var loaderInfo = loader.contentLoaderInfo; var loaderInfo = loader.contentLoaderInfo;
var stage = new flash.display.Stage; 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; loader._stage = stage;
stage._loader = loader; stage._loader = loader;
function fitCanvas(container, canvas) { function fitCanvas(container, canvas) {
canvas.width = container.clientWidth; if (canvasHolder) {
canvas.height = container.clientHeight; 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 () { loaderInfo.addEventListener('init', function () {
@ -25,27 +45,88 @@ SWF.embed = function(file, container, options) {
fitCanvas.bind(container, canvas); fitCanvas.bind(container, canvas);
}); });
} else { } else {
canvas.width = stage._stageWidth; if (canvasHolder) {
canvas.height = stage._stageHeight; 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"); container.setAttribute("style", "position: relative");
canvas.addEventListener('click', function () { canvas.addEventListener('click', function () {
ShumwayKeyboardListener.focus = stage; 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) { canvas.addEventListener('mousemove', function (domEvt) {
stage._mouseX = domEvt.pageX - this.offsetLeft; var node = this;
stage._mouseY = domEvt.pageY - this.offsetTop; 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; var bgcolor = loaderInfo._backgroundColor;
stage._color = bgcolor; stage._color = bgcolor;
canvas.style.background = toStringRgba(bgcolor); canvas.style.background = toStringRgba(bgcolor);
stage._children[0] = loader._content; var root = loader._content;
container.appendChild(canvas); stage._children[0] = root;
renderStage(stage, ctx); 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) { 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; var nextFontId = 1;
@ -18,6 +18,9 @@ function defineFont(tag, dictionary) {
var glyphIndex = { }; var glyphIndex = { };
var ranges = []; var ranges = [];
var glyphs = tag.glyphs;
var glyphCount = glyphs.length;
if (tag.codes) { if (tag.codes) {
codes = codes.concat(tag.codes); codes = codes.concat(tag.codes);
for (var i = 0, code; code = codes[i]; ++i) for (var i = 0, code; code = codes[i]; ++i)
@ -39,13 +42,15 @@ function defineFont(tag, dictionary) {
ranges.push([start, end, indices]); ranges.push([start, end, indices]);
} }
} else { } else {
var indices = [];
var UAC_OFFSET = 0xe000;
for (var i = 0; i < glyphCount; i++) { for (var i = 0; i < glyphCount; i++) {
var code = 0xe000 + i; var code = UAC_OFFSET + i;
codes.push(code); codes.push(code);
glyphIndex[code] = i; glyphIndex[code] = i;
indices.push(i); indices.push(i);
} }
ranges.push([0, glyphCount - 1, indices]); ranges.push([UAC_OFFSET, UAC_OFFSET + glyphCount - 1, indices]);
} }
var ascent = tag.ascent || 1024; var ascent = tag.ascent || 1024;
@ -130,7 +135,6 @@ function defineFont(tag, dictionary) {
format314 format314
; ;
var glyphs = tag.glyphs;
var glyf = '\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x31\x00'; var glyf = '\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x31\x00';
var loca = '\x00\x00'; var loca = '\x00\x00';
var resolution = tag.resolution || 1; var resolution = tag.resolution || 1;
@ -282,7 +286,6 @@ function defineFont(tag, dictionary) {
var advance = tag.advance; var advance = tag.advance;
var resolution = tag.resolution || 1; var resolution = tag.resolution || 1;
var glyphCount = glyphs.length;
tables['hhea'] = tables['hhea'] =
'\x00\x01\x00\x00' + // version '\x00\x01\x00\x00' + // version
toString16(ascent) + // ascender 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 = [ var defaultTemplateSet = [
readSi8, readSi16, readSi32, readUi8, readUi16, readUi32, readFixed, 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 plte = createPngChunk('PLTE', (new Array(769)).join('\x00'));
var alphaValues = []; var alphaValues = [];
@ -18,7 +18,7 @@ function defineImage(tag, dictionary) {
if (tag.mimeType === 'image/jpeg') { if (tag.mimeType === 'image/jpeg') {
var width = 0; var width = 0;
var height = 0; var height = 0;
var i = 2; var i = 0;
var n = imgData.length; var n = imgData.length;
var code; var code;
do { do {
@ -103,7 +103,7 @@ function defineImage(tag, dictionary) {
var header = tables.data; var header = tables.data;
data = header.substr(0, header.length - 2) + data; data = header.substr(0, header.length - 2) + data;
} else { } else {
data = '\xff\xd8' + data; data = data;
} }
} else { } else {
var numChunks = imgData.length / 65536; var numChunks = imgData.length / 65536;
@ -118,6 +118,8 @@ function defineImage(tag, dictionary) {
var img = { var img = {
type: 'image', type: 'image',
id: tag.id, id: tag.id,
width: width,
height: height,
mimeType: tag.mimeType, mimeType: tag.mimeType,
data: data 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]; 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) { function defineLabel(tag, dictionary) {
var records = tag.records; var records = tag.records;
@ -42,16 +42,10 @@ function defineLabel(tag, dictionary) {
} }
} }
cmds.push('c.restore()'); cmds.push('c.restore()');
var bounds = tag.bounds;
var label = { var label = {
type: 'label', type: 'label',
id: tag.id, id: tag.id,
bbox: { bbox: tag.bbox,
left: bounds.xMin,
top: bounds.xMax,
right: bounds.yMin,
bottom: bounds.yMax
},
data: cmds.join('\n') data: cmds.join('\n')
}; };
if (dependencies.length) 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 = { var tagHandler = {
/* End */ 0: undefined, /* 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,264 +1,285 @@
/* -*- mode: javascript; tab-width: 4; insert-tabs-mode: nil; indent-tabs-mode: nil -*- */ function renderDisplayObject(child, ctx, transform, cxform) {
var m = transform;
ctx.transform(m.a, m.b, m.c, m.d, m.tx, m.ty);
//function renderShadowCanvas(child) { if (cxform) {
// var cache = child.hitTestCache; // We only support alpha channel transformation for now
// ctx.globalAlpha = (ctx.globalAlpha * cxform.alphaMultiplier + cxform.alphaOffset) / 256;
// var bounds = child.getBounds(); }
// var offsetX = Math.floor(bounds.x / 20);
// var offsetY = Math.floor(bounds.y / 20); if (child._graphics) {
// var sizeX = Math.ceil(bounds.width / 20); var graphics = child._graphics;
// var sizeY = Math.ceil(bounds.height / 20);
// var scale = graphics._scale;
// var canvas = cache.canvas; if (scale !== 1)
// if (!canvas) { ctx.scale(scale, scale);
// cache.canvas = canvas = document.createElement('canvas');
// cache.isPixelPainted = function(x, y) { var subpaths = graphics._subpaths;
// x = 0 | (x - offsetX); for (var j = 0, o = subpaths.length; j < o; j++) {
// y = 0 | (y - offsetY); var pathTracker = subpaths[j], path = pathTracker.target;
// if (x < 0 || y < 0 || x >= sizeX || y >= sizeY) if (path.fillStyle) {
// return false; ctx.fillStyle = path.fillStyle;
// var data = cache.imageData.data; if (path.fillTransform) {
// var result = data[(x + sizeX * y) * 4 + 3]; var m = path.fillTransform;
// return !!result; ctx.beginPath();
// }; path.__draw__(ctx);
// } ctx.save();
// ctx.transform(m.a, m.b, m.c, m.d, m.tx, m.ty);
// if (sizeX <= 0 || sizeY <= 0) ctx.fill();
// return; ctx.restore();
// } else {
// canvas.width = sizeX; ctx.fill(path);
// canvas.height = sizeY; }
// }
// var ctx = canvas.getContext('2d'); if (path.strokeStyle) {
// ctx.save(); ctx.strokeStyle = path.strokeStyle;
// ctx.mozFillRule = 'evenodd'; var drawingStyles = pathTracker.drawingStyles;
// ctx.clearRect(0, 0, sizeX, sizeY); for (var prop in drawingStyles)
// ctx.translate(-offsetX, -offsetY); ctx[prop] = drawingStyles[prop];
// ctx.scale(0.05, 0.05); ctx.stroke(path);
// }
// if (child.draw) }
// child.draw(ctx, child.ratio); }
// else if (child.nextFrame) {
// var renderContext = { if (child.draw)
// isHitTestRendering: true, child.draw(ctx, child.ratio);
// beginDrawing: function() { return ctx; }, }
// endDrawing: function() {}
// }; function renderStage(stage, ctx, onFrame) {
// child.renderNextFrame(renderContext); var frameWidth = ctx.canvas.width;
// } var frameHeight = ctx.canvas.height;
//
// ctx.restore(); var scaleX = frameWidth / stage._stageWidth;
// var scaleY = frameHeight / stage._stageHeight;
// cache.ratio = child.ratio;
// cache.imageData = ctx.getImageData(0, 0, sizeX, sizeY); 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);
function renderStage(stage, ctx) {
// All the visitors close over this class to do instance testing. // All the visitors close over this class to do instance testing.
const MovieClipClass = avm2.systemDomain.getClass("flash.display.MovieClip"); var MovieClipClass = avm2.systemDomain.getClass("flash.display.MovieClip");
const ContainerClass = avm2.systemDomain.getClass("flash.display.DisplayObjectContainer"); 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) { function visitContainer(container, visitor, interactiveParent) {
var children = container._children; var children = container._children;
var dirty = false;
visitor.childrenStart(container); visitor.childrenStart(container);
for (var i = 0, n = children.length; i < n; i++) { for (var i = 0, n = children.length; i < n; i++) {
var child = children[i]; var child = children[i];
if (child) { if (child) {
var isContainer = ContainerClass.isInstanceOf(child); var isContainer = ContainerClass.isInstanceOf(child) ||
visitor.visit(child, isContainer); SimpleButtonClass.isInstanceOf(child);
if (isContainer) {
visitContainer(child, visitor); 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); visitor.childrenEnd(container);
if (dirty)
container._bounds = null;
} }
function EnterFrameVisitor() { function PreVisitor(ctx) {
this.ctx = ctx;
} }
EnterFrameVisitor.prototype = { PreVisitor.prototype = {
childrenStart: function() {}, childrenStart: function() {},
childrenEnd: function() {}, childrenEnd: function() {},
visit: function (obj) { visit: function (child, isContainer, interactiveParent) {
if (MovieClipClass.isInstanceOf(obj)) { if (MovieClipClass.isInstanceOf(child)) {
if (obj.isPlaying()) { if (child.isPlaying()) {
obj.nextFrame(); child.nextFrame();
} }
obj.dispatchEvent(new flash.events.Event("enterFrame")); 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 ExitFrameVisitor() { function PostVisitor() {
} }
ExitFrameVisitor.prototype = { 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() {}, childrenStart: function() {},
childrenEnd: function() {}, childrenEnd: function() {},
visit: function (obj) { visit: function (obj) {
if (MovieClipClass.isInstanceOf(obj)) { if (obj._scriptExecutionPending) {
obj.dispatchEvent(new flash.events.Event("exitFrame")); obj._scriptExecutionPending = false;
var currentFrame = obj._currentFrame;
obj._callFrame(currentFrame);
} }
} }
}; };
function RenderVisitor(ctx) { function RenderVisitor(ctx) {
this.depth = 0;
this.ctx = ctx; this.ctx = ctx;
this.depth = 0;
} }
RenderVisitor.prototype = { RenderVisitor.prototype = {
childrenStart: function(parent) { childrenStart: function(parent) {
if (this.depth == 0) { if (this.depth == 0) {
var ctx = this.ctx; var ctx = this.ctx;
var stage = parent;
var frameWidth = ctx.canvas.width;
var frameHeight = ctx.canvas.height;
var scaleX = frameWidth / stage.stageWidth; ctx.save();
var scaleY = frameHeight / stage.stageHeight;
var scale = Math.min(scaleX, scaleY); ctx.clip();
var offsetX = (frameWidth - scale * stage.stageWidth) / 2;
var offsetY = (frameHeight - scale * stage.stageHeight) / 2;
ctx.clearRect(0, 0, frameWidth, frameHeight); ctx.clearRect(0, 0, frameWidth, frameHeight);
ctx.save();
ctx.translate(offsetX, offsetY);
ctx.canvas.currentTransform = { ctx.mozFillRule = 'evenodd';
stage._canvasState = {
canvas: ctx.canvas,
scale: scale, scale: scale,
offsetX: offsetX, offsetX: offsetX,
offsetY: offsetY offsetY: offsetY
}; };
} }
this.depth++; this.depth++;
// TODO move into separate visitor?
if (MovieClipClass.isInstanceOf(parent) && parent._scriptExecutionPending) {
parent.callFrame(parent.currentFrame);
parent._scriptExecutionPending = false;
}
}, },
childrenEnd: function(parent) { childrenEnd: function(parent) {
this.depth--; this.depth--;
this.ctx.restore(); this.ctx.restore();
}, },
visit: function (child, isContainer) { visit: function (child, isContainer) {
if (child._clipDepth) {
// TODO handle masking
return;
}
var ctx = this.ctx; var ctx = this.ctx;
ctx.save(); 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; renderDisplayObject(child, ctx, child._currentTransform, child._cxform);
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;
}
if (child._graphics) {
var graphics = child._graphics;
var scale = graphics._scale;
if (scale !== 1)
ctx.scale(scale, scale);
var subpaths = graphics._subpaths;
for (var j = 0, o = subpaths.length; j < o; j++) {
var path = subpaths[j];
if (path.fillStyle) {
ctx.fillStyle = path.fillStyle;
if (path.fillTransform) {
var m = path.fillTransform;
path.__draw__(ctx);
ctx.save();
ctx.transform(m.a, m.b, m.c, m.d, m.tx, m.ty);
ctx.fill();
ctx.restore();
} else {
ctx.fill(path);
}
}
if (path.strokeStyle) {
ctx.strokeStyle = path.strokeStyle;
var drawingStyles = path.drawingStyles;
for (var prop in drawingStyles)
ctx[prop] = drawingStyles[prop];
ctx.stroke(path);
}
}
}
if (child.draw) {
child.draw(ctx, child.ratio);
}
if (!isContainer) { if (!isContainer) {
// letting the container to restore transforms after all children are painted // letting the container to restore transforms after all children are painted
ctx.restore(); ctx.restore();
} }
//if (child.hitTestCache && child.hitTestCache.ratio != child.ratio) if (stage._showRedrawRegions && child._dirtyArea) {
// renderShadowCanvas(child); 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 frameTime = 0;
var maxDelay = 1000 / stage.frameRate; var maxDelay = 1000 / stage.frameRate;
ctx.mozFillRule = 'evenodd'; var requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
var requestAnimationFrame = window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame; window.webkitRequestAnimationFrame ||
window.oRequestAnimationFrame ||
var FPS = (function () { window.msRequestAnimationFrame ||
var width = Math.max(ctx.canvas.width / 5, 100); window.setTimeout;
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;
}
};
})();
(function draw() { (function draw() {
var now = +new Date; var now = +new Date;
if (now - frameTime >= maxDelay) { if (now - frameTime >= maxDelay) {
frameTime = now; 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 RenderVisitor(ctx));
visitContainer(stage, new ExitFrameVisitor()); visitContainer(stage, new PostVisitor());
FPS.tick(); stage._syncCursor();
if (onFrame) {
onFrame();
}
} }
requestAnimationFrame(draw); requestAnimationFrame(draw);
})(); })();

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