Since April-May 2017 I started to work on providing an open source implementation of the Flash Player and other related tools. This is mainly intended for archival purposes: many interactive content of the 2000's web required Flash. Flash has many flaws (accessibility, plugin security, use for ads and tracking, proprietary nature) but loosing it would cause the loss of part of web's history.
One of the main design principles is to have self-contained composable modules. The end goal is to provide drop-in Flash support by adding an inline script (either patching <embed>
HTML tags or the popular SWFObject
library), but also integrate with other tools. I want to be able to run my player server-side (for example for headless tests), support debugging or patch host features (for example to fix frame-rate or provide determinist "random" functions).
This is implemented simultaneously in two languages: Typescript and Rust. The goal of the Typescript implementation is to have a clear architecture serving as a reference implementation and for prototyping new features. The goal of the Rust version is to have a performant implementation and eventually port it to Wasm. Implementing my components in both languages helps me to review my own code, approach problems from different perspectives and check that my components can interoperate, even across languages.
Currently, I have the following libraries:
swf-tree
: Defines an Abstract Syntax Tree representation of SWF files. This is the representation used for communication between the parser, player and future SWF emitter. It is relatively complete, apart from.abc
(Actionscript Byte Code, compiled AS3) support. The most notable thing about this AST is that it abstracts tag types. SWF files are organized as stream of blocks called "tags". Due to the evolution of the spec, some tags have multiple versions (e.g.DefineMorphShape
andDefineMorphShape2
),swf-tree
tries its best to unify most tags.swf-tree
also defines a JSON representation for interoperability.swf-parser
: Reads.swf
files into theswf-tree
AST. Both Rust and Typescript representation are written to support incremental parsing (streaming mode) even if they currently require the SWF file to be first completely loaded in memory.domu-player
: Core library for the browser version of the player. It currently contains the remaining components: player (scheduler), display tree, renderer and DOM integration. Its architecture is getting stable and it will be split in smaller components once I get a better understanding of how to organize the code.
It is currently possible to use it with HTML custom components:
<x-swf src="squares.swf" width="550" height="400"></x-swf>
<!-- Compare it to the Flash Plugin usage: -->
<embed type="application/x-shockwave-flash" src="squares.swf" width="550" height="400"/>
It currently supports static shapes, morph shapes, loops, gradients, buttons and sprites (nested elements). It has initial implementations of bitmap (images) support that needs to be completed. Remaining work involves fonts, audio and video support; as well as the Actionscript Virtual Machine and bindings with the player.
Related projects:
- Ruffle: Open Source Flash Player for the Web.
- GNU Gnash: Developed until 2012, standalone player supporting most of Flash 11
- Shumway: Developed by Mozilla from 2012 to 2016, embeddable player using Web technologies (HTML5 and Javascript). This is the main inspiration for my project. I originally wanted to just reuse its parser but its monolithic structure made it hard. That's why I'm now trying to have better component separation.
- AvmPlus and AdobeAIR: Adobe open sourced some of its tools around Flash