Skip to content

Public Variables

Josh Tynjala edited this page Mar 27, 2019 · 3 revisions

It is pretty natural and common to just declare public variables on a class. As in:

public class MyClass
{
  public var someVariable:Object;
}

However, public vars often do not survive minification and should be avoided for classes that will be used in MXML. Public methods and getters and setters will survive minification. Public "properties" for classes used in MXML should be defined via getters and setters.

If an application works in js-debug but not js-release, public variables are often at fault. The framework code has plenty of public vars because those classes were deemed to be not used from MXML. If a class with public vars does end up being used in MXML, that class should have its public vars rewritten as getter/setter.

We are still learning more about other scenarios that may fail in js-release due to renaming, so we may find that public variables always have to be rewritten as getter/setter.

The compiler has an option "-warn-public-vars" that is on by default. A warning message will be in the compiler output. The framework code should compile without these warnings. Either convert the var to getter/setter or suppress the warning via the @royalesuppresspublicvarwarning ASDoc directive. The directive can be used on each var or applied to an entire class. public vars with [Bindable] are exempt and should not cause the output of a warning because [Bindable] instructs the compiler to generate a getter/setter.

If a class is found to be at fault in js-release, check to see if @royalesuppresspublicvarwarning is used in the class and consider whether the renaming is at fault.

Technical Details

Currently, any public variable, getter/setter, or method is output with an @export directive. Such as:

MyClass = function();

/**
 * @export
 */
MyClass.prototype.somePublicThing = function() {
}

The Google Closure Compiler renames somePublicThing to something short like "ah" and then generates an export reference like this:

MyClass.prototype.ah = function() {
}
MyClass.prototype.somePublicThing = MyClass.prototype.ah;

That way, all code that used to be "myClassInstance.somePublicThing()" can be shortened to "myClassInstance.ah" saving several bytes per use. But if someone were to write "myClass.somePublicThing()" or myClass["somePublicThing"]() in another module, it will find the renamed property. @export basically provides a reference with the original name to the shortened name, it does not actually prevent renaming.

For read-only class members like the methods and getter/setters, the export reference will reference the original function and all will be good.

But for public vars, the code is going to look like:

MyClass.prototype.ah = "foo";
MyClass.prototype.somePublicThing = MyClass.prototype.ah;

The problem is, if myClassInstance.ah is given a new value, myClassInstance.somePublicThing is still "foo". It was given a reference or value of ah at startup time.

MXML, DataBinding and States expect to be able to access the property by name and thus cannot work once ah is changed or ah is passed by value.

Clone this wiki locally