Haxe 2.0 Changes

Haxe 1.0 was released more than two years ago. Since then, a lot of things have been added in Haxe, including Haxe Remoting, Flash9 and PHP support. It's sometimes good to look back at things and try to remove stuff that is no longer useful and do some clean rewrite of some part of the libraries.

That's why Haxe 2.0 was announced on 2008/03/24 with the idea that it will be allowed to break backward compatibility. This way all changes will be grouped into one single release, which will be easy for users to adapt their existing code.

Here's the list of changes for haxe 2.0 :

Override

In Haxe 1.x, it was possible to toggle the --override commandline parameter in order to get errors when some method overriding a superclass method was not declared with the override keyword.

In Haxe 2.0, this behavior becomes mandatory and each method in a subclass overriding a superclass method must be declared with override. The --override commandline switch is no longer useful and have then be removed.

This feature provides better security since you make sure that :

  • the superclass methods actually exists
  • you cannot override a superclass method by accident

Also, in order to ease programming, a method declared with override inherits the attributes of the supermethod (such as public, inline or dynamic). This way you don't have to redeclare all the attributes at the same time as override.

Dynamic Methods

In Haxe 1.x, on some currently supported platforms (Flash9 and PHP), it was necessary to declare methods that can be rebinded outside of the class as f9dynamic :

    public f9dynamic function onClose() {
    }
    //....
    myClass.onClose = myOnCloseHandler;

This was enabling runtime method redefinition, which might comes at a performance cost on some platforms.

In Haxe 2.0, f9dynamic was renamed as dynamic (which becomes a keyword) and it is now mandatory on all platforms to declare methods that can be rebinded with dynamic.

This change enable more consistent behavior across platforms, as well as a good way to know which methods can be rebinded or not, resulting in additional possibilities for performances improvement.

Impact on Anonymous objects

Before that change, it was possible to write on most platforms (excluding Flash9 and PHP) :

    var o : { pop : Void -> Int, length : Int } = new Array<Int>();

This will now raise an error since in the o case, the pop field can be rebinded while this is no longer the case for an Array instance, the pop method not being declared as dynamic.

The solution is to use the alternative notation for Anonymous objects including methods. It's a bit more verbose but it works better :

    var o : { function pop() : Int; var length : Int; } = new Array<Int>();

Since in that case pop is declared as a function without dynamic, it will be a read-only field and then compilation will work as usual.

Haxe Remoting

When first added, Haxe Remoting was supposed to only deal with Flash/JS communications. After that many other kind of other communications were added, and the code became quite messy. The whole model was also a bit unsecure since it was possible to access any object in Flash or JS using a remoting connection, leading to possible security issues.

A complete rewrite of the haxe.remoting package was then done. There are still two kind of Remoting Connections which are now interfaces :

interface Connection implements Dynamic<Connection> {
  function resolve( name : String ) : Connection;
  function call( params : Array<Dynamic> ) : Dynamic;
}
interface AsyncConnection implements Dynamic<AsyncConnection> {
  function resolve( name : String ) : AsyncConnection;
  function call( args : Array<Dynamic>, ?result : Dynamic -> Void ) : Void;
  function setErrorHandler( error : Dynamic -> Void ) : Void;
}

As you may know, a class which implements Dynamic<T> return an instance of "T" for every field access on this class. And in case a resolve methods exists (was __resolve in Haxe 1.x), then that method is called instead.

Thus, writing the following :

    var cnx : haxe.remoting.Connection = ....
    cnx.api.method.call([]);

Is actually a shortcut for the following :

    var cnx : haxe.remoting.Connection = ...
    cnx.resolve("api").resolve("method").call([]);

Context

Each connection that can receive incoming requests is now using a haxe.remoting.Context that enable fine-control over which objects are callable on the connection. The class is defined as :

package haxe.remoting;

class Context {
  function new() : Void;
  function addObject( name : String, obj : Dynamic, ?rec : Bool ) : Void;
  function call( path : Array<String>, params : Array<Dynamic> ) : Dynamic;
}

You can share an object with addObject, and allow access to all its subfields by setting rec to true (it's false by default). The ''call' method is responsible to resolve the path and call the actual method.

You can also subclass this class with your own access policy. For instance the haxe.remoting.ContextAll class is included which enable you to get old Haxe Remoting behavior to enable all objects and all fields access from the remoting connection.

Connections

The following connections are available :

AMFConnection // Flash-to-AMF server
AsyncAdapter // Turns a Connection into an Async one
AsyncDebugConnection // Allow log on an Async connection
DelayedConnection // delay messages until an Async connection is ready
ExternalConnection // Flash-JS using ExternalInterface
FlashJsConnection // Flash-Flash-through JS 
HttpAsyncConnection // Flash/JS/Neko to Http server
HttpConnection // JS/Neko to Http server (sync)
LocalConnection // Flash-Flash using flash.LocalConnection
SyncSocketConnection // Neko-server using Socket
SocketConnection // Flash/JS to server using Socket
SocketWrapper // allow JS to use Flash sockets

IO

A new haxe.io package has been added, which mostly replace the neko.io one. It contains the following classes :

Bytes // a binary fixed-sized Bytes buffer
BytesBuffer // a variable length bytes output
BytesData // the code type for internal representation of Bytes
Input // the generic reader API
Output // the generic writer API
BytesInput // input of bytes
BytesOutput // output to bytes
StringInput // input data contained in a string
Eof // exception throw when no more data available
Error // some additional IO error messages

The haxe.io.Bytes class permits crossplatform binary data manipulation. haxe.io.Bytes is also supported in haxe.Serializer and haxe.Unserializer (using base64 encoding) so you can exchange binary data between platforms using serialization or Haxe Remoting.

Conditional Compilation

In haxe 1.x, conditional compilation with using the following scheme :

#if flash
#else neko
#else true
#end

#else has been replaced by #elseif so now you'll have to change your code to write the following instead :

#if flash
#elseif neko
#else
#end

Also, #else error that was displaying the error message Not available on that platform is now simply #error.

Physical Equality

The physical equality operators === and !== have been removed from Haxe language. They were mostly not used and their behavior was inconsistent across platforms. They might remain accessible through magic apis on some platforms if needed, but are not part of the core language anymore.

Int32

A new optimized haxe.Int32 class is available which enable crossplatform Int32 manipulation. It replaces neko.Int32 and has been optimized with inline in order to ensure good speed on platforms where there is native Int32 support.

Resources

Resources are now available by using the haxe.Resource api. It allow to directly access bytes of stored resources. You can use haxe.Resource.getString instead of Std.resource.

Parameters default values

You can now specify default value for optional parameters :

    function foo( x : Int, ?y : String = "hello" ) {
    }

Only constant value are allowed.
In Flash9, this will optimize the basic types since they will no longer be Null (unless you specify it yourself).

Local variables Initialization

It is now required to initialize a local variable before using it.
For instance the following does not work anymore :

var a;
if( cond ) a = new Array();
trace(a);

You'll have to use var a = null instead. OTOH, the compiler is checking if a variable is initialized in all the different possible paths, so the following is still allowed :

var a;
if( cond ) a = new Array(); else a = null;
trace(a);

Library Changes

The following classes have been removed :

  • neko.io : Input, Output, Eof, Error, Logger, Multiple, StringInput, StringOutput : they are replaced by the haxe.io package classes
  • neko.net.RemotingServer : is now split into haxe.remoting.Context and haxe.remoting.HttpConnection.handleRequest
  • neko.Int32 : is now haxe.Int32

The following methods have been removed :

  • Std.bool : use your own definition of what should be true or false
  • Std.chr : use String.fromCharCode(xxx)
  • Std.ord : use .charCodeAt(0)
  • Std.resource : use haxe.Resource.getString instead
  • Type.toClass / Type.toEnum : use a cast for Dynamic values, no cast needed otherwise
  • Reflect.empty : use {} instead
  • haxe.Timer.delayed : use haxe.Timer.delay instead
  • haxe.Timer.queue : use new haxe.TimerQueue class instead
  • haxe.Stack : has complete support for Flash9. Order of Neko stack elements has been reversed to match Flash/JS ones
  • haxe.rtti.Type has been renamed to haxe.rtti.CType
  • added Reflect.createEnum

Haxe/PHP integration

Starting from 2.0, the Haxe/PHP generator developed by Franco Ponticelli will be added to official Haxe distribution.

version #8339, modified 2010-03-20 21:29:47 by mpe