2020 Prepping and Updates

Even if I posted a little about this or that, time to make a little recap of what’s been happening into Redtamarin for the last few years :stuck_out_tongue:

let’s summarize it like that

Developers, Developers, Developers


The main philosophy behind Redtamarin, and OK I may have not communicated too well about that, is that it is heavily developers oriented, as “people who do write code” and you add “with ActionScript 3”

That’s it, if you’re somewhat comfortable with AS3, as a dev it should take you about 1 day to adopt Redtamarin, provided

  • you’re not averse to the command-line
  • you’re able to read documentations to learn new API
  • you’re not lazy and are able to write code

And if you never dabbed with ActionScript before,
coming from JavaScript, C, C++, PHP, etc.

You should be able to cruise into AS3 in a couple of days, really.


Not averse to the command-line

Ok this is a dead beaten horse that I really wish I should not debate anymore, but in 2020 if you consider yourself a developer and don’t touch the command-line, you’re doing it wrong and I can guarantee you, this is something you will regret dearly in the years to come.

Before I was more like “you SHOULD learn the command-line”, as an option if you have time, maybe spend a little time with it to learn the basic.

Now, that’s not valid anymore, it is like “you HAVE TO learn the command-line”, it is not optional, if you don’t know it, it will cripple you learning stuff related to programming.

Most if not all JS frameworks, from React to Vue, all get installed from the CLI, all their tutorials starts with the CLI (usually with npm install something), and they requires basic knowledge of some CLI tools like: tsc, webpack, gulp, babel, etc.

Even sites likes w3schools.com got a little tidbit about the CLI

What is Command Line Interface (CLI)?

C:\>npm install mysoftware

CLI stands for:

  • Command Line Interface
  • Command Line Interpreter
  • Command Line Input

Redtamarin is no different than any other programming environments, most of our tools start with the CLI, and maybe later we’ll have more GUI stuff, but that’s not essential really.

There are a series of posts in the #cli category to get you started
https://discuss.as3lang.org/c/cli

but depending on your environment or OS or preferences, there are plenty more tutorials online

the little snarky comments like “oh redtamarin does not supports GUI, it sucks”
sorry does not work anymore, you’re free to not want to learn the CLI
see you in few years when your comment will change to “oh shit I should have learned the CLI earlier”

Now if you can learn a bit of npm, a bit of webpack etc. just to run a JS app in the browser, learning a bit of Redtamarin command-line tools not gonna take you very long, but in order to do that you need to be willing to at least open a command prompt, we can not do that part for you.

The only things we can guarantee is that our tooling will be cross-platform,
the same way you can find JavaScript shells we have our own ActionScript shells and various tools to help build and manage ActionScript projects.

I could copy/past a long stuff from the doc, but all those tools are plenty documented in details in the docs, see next paragraph.


Documentations

An atrocious (yes it is that dramatic) amount of time have been spent writing documentations.

First, the tooling, any tools distributed with the Redtamarin SDK has its own man page, so for ex: if you have a tool named redtamarin, to know all the details about it you just need to type man redtamarin.

We even added man pages to tools that had none, the Redtamarin shells like redshell based out of the avmshell from the avmplus project have many options, we kept those and so we documented those too , eg. you will be able to do a man redshell

example

And if your OS does not supports man pages, like a default Windows command-prompt, the man page is available as an HTML or PDF document (ideally we will have a command for that, for ex: redtamarin doc redshell).

But all that was not the main effort for documenting, I mentioned bit of those earlier in posts
like Community Documentation Projects.

First big effort was the AS3LCR (ActionScript 3.0 Language and Component Reference), that is the API that are available to the runtimes.

Not only we had to document what the Redtamarin was adding, but also the Flash API and also the AIR API, etc.

Problem is that implementing the Flash/AIR API is something that can not happen overnight, but for community sake, if https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/ goes down, we want to be able to go somewhere and read the doc about those API.

So we took the approach of a 100% API documentation coverage for Flash Player 9.0 and AIR 1.0 (and extras if/when possible). The “extras” can be other versions than FP9/AIR1 and/or can be undocumented stuff.

And at the same time we took a rule of 100% API definitions, even if not implemented or not fully implemented, there we add extras to the doc so you know what works or not with the API from within Redtamarin.

Let’s take for example the flash.system package

In short, the listing of definitions (classes, interfaces) would be the same in the Redtamarin documentation, or would have more definitions (for ex: undocumented classes).

the official AS3LCR does not document System.vmVersion but we do

When possible we write the documentation for undocumented stuff, but it is not always possible considering the informations available in the wild.
At least we tell you “it is there” and you can use it.

in the See also you will notice often links with the :cyclone: (cyclone emoji)
we have all of these

  • Undocumented Hidden
  • Capabilities of different profiles
  • Stub
  • No Operation
  • Require Async
  • Unsupported in Background Workers
  • APIs with behavioral changes in background Workers

where we explain why things work like that or why there is limitations or differences in the Redtamarin shells etc.

if we take another example with System.exit()

that’s basically the same doc as the AS3LCR but you get that link to “APIs with behavioral changes in background Workers” where you can learn that System.exit() when executed from inside a child worker terminate that worker instead of exiting the runtime itself.

Another example would be System.pause()

Here we mark it as “No Operation”, to tell you the Redtamarin shells do not implement it.
The definitions is here as part of the 100% coverage for documentation and for API compatibility (eg. you would not want to break your program if you call System.pause()) but calling that particular result in a NO-OP (No Operation).

And that is the same for every single API embedded in the Redtamarin shells.

We follow the same format as the AS3LCR but we added numerous appendixes,
for every packages you will be able to know their implementation status

to read with the associated legend

so OK this screenshot is a bit out of date but you get the idea

Also for every packages we try to provide implementation notes (in short why we did it like that)

again a bit out of date, as the functionality for ApplicationDomain.getQualifiedDefinitionNames() got implemented only recently see this gist https://gist.github.com/zwetan/cf839594c417ef178e8fe019650b17d3

or here on twitter


The goal of all these docs is even if you don’t plan to use Redtamarin, at least you should be able to use the HTML generated from asdoc as a replacement for the AS3LCR.

The other documentations are in the same idea as the “books” mentioned earlier
eg. Community Documentation Projects.

With the Redtamarin SDK, you well get the “Redtamarin Software Development Kit Reference” (redsdk-book), and depending on your needs and under the as3lang labe you also get access to other books like “ActionScript 3 Language Specification” (as3spec-book), “ActionScript 3 Ecosystem Starter Pack” (as3esp-book), etc.

Something like the AS3LCR is useful but not close to enough, Inside the redsdk-book you would find things like “How to build a command-line tool”, “How to build a REST API”, etc.

The same way the ActionScript 3.0 Developer’s Guide can provide you with hands-on examples on how to deal with “Rich Media Content” or “Files and data” etc.


So yeah all that doc takes a hell lot of time, I think it is worth it, well we’ll see.

In the end, if your expectation if to replace Flash or AIR with Redtamarin, those documentations should tell you from the get go, nope not gonna happen.

Off course, we will try to implement a maximum of API from Flash/AIR but as always we will focus on the CLI, for example: being able to reuse an already existing SWC you used earlier for an online SWF or an AIR app is something we plan for, but don’t expect it to work as if it was Flash or AIR (a GUI context), no no no , if it can work it will be in a CLI context no matter what.

Which lead to the next part.


Able to write code

There are many ways to write code, depending of your environment you are more or less assisted to do so.

Take something like PHP or Node.js one of the great feature is the wealth of libraries you can access from composer or npm, but this is not always a good feature.

You know the classic joke about node modules

when libraries go too granular you end up with stupid “one liner” stuff like
is-positive - Check if something is a positive number
user-home - Get the path to the user home directory
etc.

and same with PHP composer when browsing Packagist (The PHP Package Repository)
the library you might find there may have been written by some not so experienced dev while he/she was learning to use PHP, so yeah there is the merit that the lib exists, but the quality, the real value added could be quite poor (and I will pass on a long tirade about how every goddam PHP lib related to shared memory sucks).

Depending on which programming language you use you might end up with different libraries pros and cons, depends on the PL features, depends on the tooling associated, depends on the particular culture (and open source culture) adopted by the dev, etc.

I would say, with AS3, we didn’t end up with one liner libs like is-positive.swc for few reasons

  • first, as a superset of ECMAScript 3
    there are many quirks of JS we did not have to deal with
  • second, most importantly AS3 is very close to Java to manage libraries
    like Java pre-compile into a .jar, AS3 pre-compile into a .swc
    and that’s what usually is shared as a fat library
  • so culturally, it was much easier to add the “is-positive” logic
    in some Utils class or even a single function in a com.myapp.utils package
  • you could still depends on many libraries with different versions etc.
    but those libs were usually of the “fat” caliber to end up in a SWC
    anything simple enough to be only 1 function or 1 class ended up as single .as file
    for ex: the mrdoob’s Stats.as
  • also because of packages and namespaces you don’t end up with the clusterfuck of module import/export
  • ultimately, when dev realise that even with a biiiiig phat 100MB SWC, they end up using only what they import (maybe 10KB and not the whole size of the SWC) it push dev to create libraries with more than just a one poor function

Anyway, the point in all that is that your dev environment (the PL and tooling associated with it) will put you in this pros vs cons choice, where the trade of using those may have a something “like a price to pay”

  • if I want to use JS and Node.js, the price to pay is to deal with npm and lib dependencies nightmare
  • if I want to use PHP and composer, the price to pay is to deal with poor quality libraries
  • I could stop here but let’s see few more PL
    • the price to pay for using Python? the big mess of v2 vs v3
    • the price to pay for using Swift? not working under Windows
    • the price to pay for using Go? the remote import url
    • etc.

OK, great, no single dev environment is perfect.

And what about ActionScript 3.0 ? no price to pay there?

I let you think a couple of minutes :slight_smile:

Off course, there are price to pay for AS3

  • no package manager
    • which is kinda good when lot of people use AS3 and you just need to follow some blogs or RSS feed to get the latest news in libraries
    • which is kinda bad when everyone else use a package manager of some sort
      and suddenly AS3 is much less popular, you almost have to struggle to find some libraries
      hummm … could it exists? let me search on google … oh it exists!?! hu oh it’s still hosted on google code and not moved to github …
  • things that depends on Flash component
  • things that depends on Flex framework
  • hu ho now I need one ANE, euh two ANE, euh 15 ANE

These and few other things created a kind of culture for AS3 libraries where

  • dev expect things pre-packaged
    • they want a SWC, not a build to generate the SWC
    • they want an ANE, and certainly not build the ANE themselves
  • a somewhat poor knowledge of building libraries
    • the difference between
      -compiler.library-path [path-element] [...]
          alias -library-path
          list of SWC files or directories that contain SWC files (repeatable)
      
      and
      -compiler.external-library-path [path-element] [...]
          alias -external-library-path
          list of SWC files or directories to compile against but to omit from
          linking (repeatable)
      
    • the tooling is there but few use all the extend of it
  • the kind of expectation that the library will work everywhere
    • coming from a long history of Flash
      aka just output a SWF and drop it in the browser
    • coming from a long history of Flex
      confusion between Flex the IDE, Flex the framework, Flex the compiler tools

So here what I mean by able to write code, despite the pros and cons of your dev environment, despite the libraries available or not, despite the package manager or not, at the end when a dev want to output a program he or she is forced to do some choices.

And in Redtamarin, again probably poorly put up front and center, one other of the main philosophy is to give the developer many many many choices.

Let take for example the Flash/AIR API you are all used to from the flash.* package
this one in many parts depends on an “event system”, so if there is no support for that,
already half of the API can not be implemented “as is”.

so the basic doc about events
ActionScript 3.0 Developer’s Guide / Core ActionScript Classes / Handling events

An event-handling system allows programmers to respond to user input and system events in a convenient way. The ActionScript 3.0 event model is not only convenient, but also standards-compliant, and well integrated with the display list. Based on the Document Object Model (DOM) Level 3 Events Specification, an industry-standard event-handling architecture, the new event model provides a powerful yet intuitive event-handling tool for ActionScript programmers.

The ActionScript 3.0 event-handling system interacts closely with the display list. To gain a basic understanding of the display list, read Display programming .

it is all good, but do not really go into the details between synchronous and asynchronous events

you find more details here
Optimizing Performance for the Flash Platform / Rendering performance / Asynchronous operations

Synchronous operations run as soon as your code tells them to, and your code waits for them to complete before moving on. Consequently, they run in the application code phase of the frame loop. If a synchronous operation takes too long, it stretches the size of the frame loop, potentially causing the display to appear to freeze or stutter.

When your code executes an asynchronous operation, it doesn’t necessarily run immediately. Your code and other application code in the current execution thread continues executing. The runtime then performs the operation as soon as possible, while attempting to prevent rendering issues. In some cases, the execution happens in the background and doesn’t run as part of the runtime frame loop at all. Finally, when the operation completes the runtime dispatches an event, and your code can listen for that event to perform further work.

Asynchronous operations are scheduled and divided to avoid rendering issues. Consequently, it is much easier to have a responsive application using asynchronous versions of operations.

And that is a bit harder to support in Redtamarin.

The basic of having an IEventDispatcher interface, Event and EventDispatcher class, as long as it is synchronous is kind of easy.

The problem is when you need it or want it to be asynchronous.

This is where you get why I was talking about Node.js and PHP, and about choices.

In Node.js, the default is asynchronous, you have a big event loop, and most API provide a function callback for when the event occurs

see

by default if you use fs.readFile() this is asynchronous or non-blocking
and to force a synchronous or blocking call you use fs.readFileSync()

In the Flash/AIR API, you have the equivalent
FileStream.open() - Opens the FileStream object synchronously, pointing to the file specified by the file parameter.
FileStream.openAsync() - Opens the FileStream object asynchronously, pointing to the file specified by the file parameter.

And with PHP, it’s the opposite, by default everything is synchronous, there is no event loop
if you want such thing you will need a 3rd party library like ReactPHP
and you can read a bit more here Asynchronous PHP: Why?

Finally, in the case of Redtamarin, it comes to the dev choice.

Sure we have a default, like C/C++ programs, exe and binaries of all sorts running on the command-line, by default, we are synchronous or blocking.

And AS3 events, provided they are not asynchronous, will work perfectly fine with that.

But as a dev you also have a choice to go all asynchronous or non-blocking, just use
Runtime.goAsync().

In general, it will be indicated in the documentation with Require Async when something need asynchronous to be able to work

As an option, we may reserve some API to force going into async mode as soon as you call them, but “to be decided”, and will probably end up being configurable, for ex: config.enableAutoAsync = true; and other options like stop the event loop when all events are consumed etc.

But here the important part is that you have the choice.

And the choice is at multiple level, all that depends on how far deep you want to go into writing the code.

Let’s say for example, you want to do a simple socket connection, you can simply reuse flash.net::Socket and all of its events, and Runtime.goAsync() and add a listener for when the work is done on the socket to, for example, stop the event loop.

At another level, you might prefer to use shell.network::TCPSocket which also use events but work in blocking mode and so does not force you to go into async mode.

And yet at another level, for whatever reasons, all that is not convenient to you, you can go deeper and reuse the BSD sockets in the C API C.sys.socket and use socket(), connect(), send(), recv(), etc.

Like take Beej’s Guide to Network Programming excellent tutorial
and port the C code directly to AS3

from that

// connect to www.example.com port 80 (http)

struct addrinfo hints, *res;
int sockfd;

// first, load up address structs with getaddrinfo():

memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;  // use IPv4 or IPv6, whichever
hints.ai_socktype = SOCK_STREAM;

// we could put "80" instead on "http" on the next line:
getaddrinfo("www.example.com", "http", &hints, &res);

// make a socket:

sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);

// connect it to the address and port we passed in to getaddrinfo():

connect(sockfd, res->ai_addr, res->ai_addrlen);

to this

// connect to www.example.com port 80 (http)
import C.sys.socket.*; // AF_INET, SOCK_STREAM, socket(), connect()
import C.netdb.*; // addrinfo, getaddrinfo()

var sockfd:int;
var res:addrinfo;

// first, load up address structs with getaddrinfo():

var hints:addrinfo = new addrinfo();
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;

// we could put "80" instead on "http" on the next line:
var addrlist:Array  = getaddrinfo( "www.example.com", "http", hints );
res = addrlist[0];

// make a socket:

sockfd = socket( info.ai_family, info.ai_socktype, info.ai_protocol );

// connect it to the address and port we passed in to getaddrinfo():

connect( sockfd, info.ai_addr );

So, being able to write code and having many choices, right?

Considering the amount of people who wrote their own ANE, I do not expect a lot of people to use the C API in Redtamarin, and yet it is integral to the design of how things work.

It is not like the ANE, and it does not use FFI (Foreign function interface) either

The Redtamarin C API is a custom binding to the C and POSIX API, in fact it is a very old school way to do things (FORTRAN and Ada did kind of like that too), but there are reasons why it is done like that (read in depth details here The Unix C library API can only be reliably used from C, among many other reasons, for ex Some reasons for Go to not make system calls through the standard C library).

And yeah it got pros and cons, off course, always pros and cons :smiley:

  • the pros
    • it is available right there on the AS3 front-end
      no need to pre-compile some C code as an external library like a .dll or .so etc.
    • you can extend what Redtamarin can do with the C API
      no need to compile C or C++, just write AS3 and follow the docs
    • you can write code at a fairly low level
      so if you have very specific or special needs you can implement them
    • it is pretty flawless to integrate in your AS3 code
      and follow the rules of AS3 for packaging, libraries, etc.
  • the cons
    • you can not just use and import any external C libraries
    • if the C definition is in the C API you can use it, if not then can’t be used
      but it is an OSS project so requests for “missing” API are welcome to be discussed
    • it is not an automatic process, you will have to write and port code
      eg. you can not import OpenSSL and just use it

Basically it’s like writing C but in an AS3 world, you might like it, you might hate it, but I can guarantee you it is extremely powerful, most if not all of the Flash/AIR API are implemented with that C API).

On my side I try to provide a lot: implementations and documentations, but sure there is always something that could be “not there”.

Let’s say for some reason you’re porting an app from Node.js to Redtamarin (hint hint :upside_down_face:)
and in this JS app a Node.js API is used, for example: os.homedir()
and either the Redtamarin API does not provide the equivalent or provide it but work slightly differently, whatever, you want to write your own os.homedir().

the Node.js doc for homedir show that

os.homedir()

Added in: v2.3.0

  • Returns: <string>

Returns the string path of the current user’s home directory.

On POSIX, it uses the $HOME environment variable if defined. Otherwise it uses the effective UID to look up the user’s home directory.

On Windows, it uses the USERPROFILE environment variable if defined. Otherwise it uses the path to the profile directory of the current user.

if you digg into the Node.js sources, you can find how they implemented it

basically it depends on basic C functions like getenv() and getpwuid_r()
Redtamarin does provide getenv() but does not provide getpwuid_r()

so a basic straightforward implementation would look like that

package nodejs
{
    import C.stdlib.*; // getenv()
    import shell.Runtime;

    public const os:Object = {};
                 os.homedir = function():String
                 {
                    var homedir:String = "";
                    var found:String = null;

                    switch( Runtime.platform )
                    {
                        case "linux":
                        case "macintosh":
                        found = getenv( "HOME" );
                        break;

                        case "windows":
                        found = getenv( "USERPROFILE" );
                        break;
                    }

                    if( found != null )
                    {
                        homedir = found;
                    }

                    return homedir;
                 }
}

(note: it could be implemented in a lot of different ways)

so if in JS you would do

const os = require('os');
console.log( os.homedir() );

then in AS3 you would do

import nodejs.*;
trace( os.homedir() );

And if you absolutely need it maybe post a github issue to add getpwuid(), getpwuid_r() to the C API later.

So yeah the example might be ridiculously simple but the point is you can add close to native stuff with the C API, without going into the hardship of building and compiling your own ANE to extend the runtime, it is by design.

It’s not perfect, it has limitations off course, but if you’re able to write some code in AS3 you will hardly be stuck without a solution, yep even when the API you need is not there.


Other features that might not shine right away are the runtime compiler and disassembler.

If you’re already worked with Workers, you know that dealing with multiple type of child workers can be a bit of a pain because you have to pre-compile them.

In my case with Redtamarin, there is no way I would implement all those async stuff in pure C/C++; well… it is possible, but I can not even fathom the pain it would cause :smiley:

And the same way the event loop is basically and simply done in AS3, and as far a choice goes you can override it with your own event loop implementation if you need to, it is the same for the implementation of async stuff.

I was talking about flash.net::Socket earlier, the async parts are just a mix of workers and synchronisation with the event loop, if I could illustrate with pseudocode the connection timeout

eg. Socket.timeout

Indicates the number of milliseconds to wait for a connection.

If the connection doesn’t succeed within the specified time, the connection fails. The default value is 20,000 (twenty seconds).

In a crude way this is simply a worker that use the C API connect() in blocking mode
and the event loop that check how long elapsed from the “start of connection”
and if it goes >= then timeout, it just terminates the worker and then dispatch a SecurityErrorEvent “Socket timeout.”.

  • socket.connect()
    • do internal stuff that get you a socket descriptor (int)
    • register a callback with the event loop
    • spawn a child worker
      • pass the socket descriptor argument
      • use C connect() which is blocking and so wait forever
    • the callback with the event loop
      check either if the connection succeeded
      or if the connection start time is greater than the timeout
    • either case the worker is terminated then an event is dispatched

The worker code is very minimalist, it does not need to do much but thanks to the runtime compiler it is just few lines of plain text that is compiled and executed at runtime.

There are a lot of “mini workers” doing such petty minimal async tasks like that,
if I had to pre-compile them all before embedding them and compiling the final Redtamarin code I would go nuts.


All in all, it ends up with what API are available to you as a developer who might be interested in writing some AS3 programs for the CLI or the server.

All those “prepping”:

  • how we design those API
  • what need to be embedded or not
  • what need to be supported or not
  • testing those API
  • documenting those API
  • etc.

I think Redtamarin is shaping up nicely, and yeah still many many many things are missing.

So yeah it’s not there yet, but when it will be, it will be usable or at least you would know by reading the docs what you can do with it.

3 Likes