Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

We have two conditional compilation flags:  COMPILE::AS3 SWF and COMPILE::JS

Base Classes

...

 

Code Block
/**
 * class documentation
 */
COMPILE::AS3SWF
public class Button extends UIButtonBase
{
}
…
COMPILE::JS
Public class Button extends UIBase
{
}

 

When examining a source file, if you see a COMPILE::AS3 flag SWF flag on the line before “public class”, you are pretty much guaranteed to find a COMPILE::JS flag later in the file.

...

The majority of UI components extend UIBase both for SWF and JS versions.  In those cases, there is no COMPILE::AS3 flag SWF flag on the line before “public class”.  Instead COMPILE::AS3 and SWF and COMPILE::JS flags are scattered throughout the source file.  There are two patterns of usage:
1:  Per-definition.  Entire functions and vars (but not import statements) can be controlled by a conditional compilation flag of the form:

 

Code Block
COMPILE::AS3SWF
public var someVar:Object;


COMPILE::AS3SWF
public function someFunction():void
{
}

 

2: Per-block.  Individual or groups of import statements and chunks of code in method bodies can be controlled by a conditional compilation flag of the form:

 

Code Block
COMPILE::AS3SWF
{
  import somePackage.someClass;
}


public function foo():String
{
    COMPILE::AS3SWF
    {
       return “hi”;
    }
    COMPILE::JS
    {
        return “bye”;
    }
} 

 

...

Sometimes a component only needs to exist for the SWF version and the class dependencies don't require that a class is defined for the JS version (and vice-versa).  An example is the ScrollBar-related code.  The SWF versions of Container and List are capable of using ScrollBar-capable views but the JS version of Container and List and their views don't reference Scrollbars because they are built into the browser's DIV (the JS views simply toggle ScrollBar-related styles on the DIV).  Same for Borders and Backgrounds.  For cases like these, the components have so far never been in the MXML manifest and are only listed in the XXXClasses file (for Core.swc, CoreClasses.as).  The pattern to use is to use COMPILE::AS3 or SWF or COMPILE::JS around the line for that component in the XXXClasses file.  If you use the "Different Inheritance" pattern above, it can cause errors as then the source file actually looks empty to the compiler.  So the best option is not to compile it at all.  Below is an excerpt from CoreClasses.as.

 

Code Block
    import org.apache.flex.utils.EffectTimer; EffectTimer;
    import org.apache.flex.utils.MixinManager; MixinManager;
	COMPILE::AS3SWF
	{
	    import org.apache.flex.utils.PNGEncoder; PNGEncoder;
    	import org.apache.flex.utils.SolidBorderUtil; SolidBorderUtil;
	    import org.apache.flex.utils.StringTrimmer; StringTrimmer;
    }
	import org.apache.flex.utils.Timer; Timer;
    import org.apache.flex.utils.CSSUtils; CSSUtils;
	COMPILE::JS
	{
	    import org.apache.flex.utils.Language; Language;
	}

In this snippet you can see that PNGEncoder, SolidBorderUtil and StringTrimmer are only needed for SWF versions, and org.apache.flex.utils.Language is only used in JS versions.

Anchor
JSSWC
JSSWC

SWF- or JS-specific APIs

Each SWC project is allowed to have public APIs that are used for communicating with other SWCs and not for use by the application developer.  For example, the JS implementations may want to address the Window object directly.  While it is possible to wrap-up and abstract away these differences between the SWF and JS runtimes, those abstractions can have performance issues, so instead we are currently opting to allow differences in public APIs based on the runtime.

So, each SWC project actually produces two SWCs.  One we call the "JS" SWC that may have JS-specific APIs, and the main SWC that has the byte code for the SWF and the cross-compiled JS files and can have SWF-specific APIs.  A future task is to upgrade the documentation system to mark certain APIs as runtime specific so the application developer knows which APIs will exist on both runtimes.

The "JS" SWC is identified by having "JS" appended to the SWC name, so there is a Core.swc that contains SWF byte code and cross-compiled JS files, and a CoreJS.swc that contains the JS-specific APIs.  Downstream SWC projects then use Core.swc for building the main SWC and CoreJS.swc for cross-compiling and building its own "JS" sec for its downstream customers.

Build-related Files

There are several files involved in building the main SWC.  The goal is to cross-compile the JS version, then compile the SWF version and create a  SWC that includes the .JS files from the cross-compile.

For each SWC project, there will be a frameworks/projects folder (i.e. frameworks/projects/HTML) and a frameworks/js/FlexJS/projects/ folder (i.e. frameworks/js/FlexJS/projects/HTML).  In addition, there are two output folders of SWCs.  The main SWCs go in frameworks/libs, the "JS" SWCs go in frameworks/js/libs.

The process for building all of the SWCs is to first build the "JS" SWCs and cross-compile the AS to JS with COMPILE::AS3SWF=false and COMPILE::JS=true.  This generates the SWCs that go in frameworks/js/libs, and target/generated-sources folders in each of the projects in frameworks/js/FlexJS/projects.  

The next step is to build the main SWFs.  The builds compile the AS with COMPILE::AS3SWF=true and COMPILE::JS=false.  They package up the JS files from target/generated-sources in the project's frameworks/js/FlexJS/projects folder.

The build.xml file for a "JS" SWC should have two main targets:

  1. compile-asjs:  This cross-compiles the JS version using the js.swc from Falcon (as opposed to playerglobal.swc or airglobal.swc) for the "built-in" classes (Object, Array, String, Number, etc).  The COMPILE::AS3 flag SWF flag should be false and the COMPILE::JS flag should be true.
  2. compile-js-swc:  This compiles a SWF for a SWC but still using the js.swc from Falcon.  This SWC is placed in an js/libs folder for use as a dependent SWC by downstream SWCs.  This SWC is needed so that only the API surfaces exposed by COMPILE::JS are available to consumers of this SWC.  Application developers should never need to access these SWCs, only downstream SWC developers.

The build.xml file for a SWC should have 3 main steps:

  1. compile: This is the final phase that compiles a SWF for a SWC with COMPILE::AS3 true SWF true and COMPILE::JS false and using playerglobal.swc or airglobal.swc for the built-in classes.

 

The list of files that are compiled by each phase is controlled by a compile-js-config.xml file for steps 1 and 2, and compile-as-config.xml for step 3.  

The compile-js-config.xml file

  • Should have an empty external-library-path entry.  The external-library-path is specified in build.xml so we can use Ant to resolve the reference to js.swc in the Falcon repo
  • Should use upstream SWCs from the js/libs folder, not the frameworks/libs folder (so that the API surfaces are the ones exposed by COMPILE::JS

The compile-as-config.xml file

  • Should have playerglobal.swc or airglobal.swc as the external-library-path entry
  • Should use upstream SWCs from the frameworks/libs folder and not the js/libs folder
  • Should have "include-file" entries for the js/FlexJS/projects/<projectname>/target/generated-sources folder
Code Block
    <include-file>
        <name>js/out/*</name>
        <path>js<path>../../../../../js/FlexJS/projects/<projectname><projectname>JS/target/generated-sources/flexjs/*<<</path>
    </include-file>

The build.xml not only includes the JS files in the JS SWC folder, but also copies them to frameworks/js/FlexJS/generated-sources.  The FalconJX compiler is told to look at frameworks/js/FlexJS/generated-sources first, then look in the SWCs.  This is done to enable folks to monkey-patch JS files in frameworks/js/FlexJS/generated-sources and not have to rebuild a SWC.  The danger is that a stale file in frameworks/js/FlexJS/generated-sources can override your changes that went into the SWC.