0

Since yesterday, I've been trying to port an ActionScript Mobile project from Flash Builder 4.6 to Flash Builder 4.7, and I've run into a little bit of a problem that's probably a compiler bug. In FB 4.6, this works:

Temp.as:

package
{
    import flash.display.Sprite;

    public class Temp extends Sprite
    {
        public function Temp()
        {
            new StartMenu();
        }
    }
}

Screen1.as:

package
{
    import flash.display.*;

    internal class Screen1 extends Sprite
    {
        private static var m_vScreens:Vector.<Screen1> = new Vector.<Screen1>();

        public function Screen1()
        {
            m_vScreens.push(this);

            onScreenSizeDetermined();return;
            var strFunction:String = "useSmallPortraitLayout";
            for each (var screen:Screen1 in m_vScreens)
            {
                trace(1)
                screen[strFunction]();
            }
        }

        protected function useSmallPortraitLayout():void
        {
        }

        private static function onScreenSizeDetermined():void
        {
            var strFunction:String = "useSmallPortraitLayout";
            for each (var screen:Screen1 in m_vScreens)
            {
                trace(2)
                screen[strFunction](); // Error thrown here in 4.7.
            }
        }
    }
}

StartMenu.as:

package
{
    public final class StartMenu extends Screen1
    {
        override protected function useSmallPortraitLayout():void
        {
        }
    }
}

But in 4.7, it doesn't work. The error I get back is this:

ReferenceError: Error #1069: Property useSmallPortraitLayout not found on StartMenu and
there is no default value.

Now that being said, this can be fixed in one of at least two ways:

  1. Use Flash Builder 4.6
  2. Comment out onScreenSizeDetermined();return;, thereby using a member function to call useSmallPortraitLayout(), instead of a static function. This doesn't require using the constructor; it works just fine, as long as Screen1 is calling useSmallPortraitLayout() from pretty much any non-static method.

Unfortunately the static method will fail, even when it's called from outside the constructor and/or from a timed delay. One thing I don't specifically remember in 4.6, but I am seeing it in at least 4.7, is that using an unrelated class to call a static method directly through an instance won't compile - it has to be done in a staticky way in unrelated classes. Not that I do things like that in real code, but it does make me wonder if the relationship between static and non-static has intentionally changed.

This is probably just some trivial compiler bug specific to FB 4.7, and I would just go right back to 4.6, but pure ActionScript library projects are directly supported only in 4.7. (This is a mobile project, but I was going to add a library project to the solution.)

One thing to note is the code will not compile in FB 4.7 if the static function calls useSmallPortraitLayout this way:

screen.useSmallPortraitLayout();

It has to call it dynamically for it to even compile.

Is there an easy-enough fix for this? Has there been a little bit of syntactical weirdness that 4.6 has simply been overlooking this whole time? What's wrong, and what's a good solution/work-around?

UPDATE

If worst comes to worst, it does seem to work to partially replace the Vector.<Screen1> with a Vector.<Function>, and then just make calls to the members of the function vector, instead of to functions of the members of the Screen1 vector. (This is simplified from production code.) But that's just a fallback.

Also, something I wasn't paying a lot of attention to previously (specifically as far as this one problem goes), but BotMaster kind of brought it to my attention, is that in the process of going from FB 4.6 to FB 4.7, I also went from AIR 3.1 to AIR 3.4.

Panzercrisis
  • 4,590
  • 6
  • 46
  • 85
  • In the actual code, there's several related functions that got named according to certain sets of circumstances. – Panzercrisis Feb 10 '15 at 16:17
  • Fair enough, I deleted my pervious comment anyway because I re-read the question and noticed the "One thing to note is the code will not compile in FB 4.7 if the static function calls " part. – CyanAngel Feb 10 '15 at 16:18
  • 1
    My suggestion (I cant back this up as I don't have FB4.7) is that they've changed how objects are initialized, such that the none static functions cant be accessed untill after the constructor is finished, try delaying your call to the static function with a `callLater` or `setTimeout` – CyanAngel Feb 10 '15 at 16:22
  • @CyanAngel Thanks! Unfortunately it still gave the same error, but that was a good idea. – Panzercrisis Feb 10 '15 at 16:37
  • Flash Builder 4.7 uses ASC 2.0, as I understand. This does explain the difference. One thing I think ASC 2.0 did differently was more optimization... could it be that ASC 2.0 actually notices there is no reference to `useSmallPortraitLayout()` and it actually excludes it from the compiled ABC? Seems a stretch, but try adding a direct reference to it somewhere and then see if you are original code works again. – Aaron Beall Feb 10 '15 at 17:21
  • Just checked the release notes and it specifically mentions "dead code elimination" as an optimization. Since I'm highly suspect that this is the behavior you're seeing, I've added an answer. – Aaron Beall Feb 10 '15 at 17:31

2 Answers2

1

This is more a scope issue imo. Protected method can only be called within the instance scope and not within a static scope. Of course changing the modifier to public fixes the issue here. PO might argue that protected is wanted here but in reality if there is intention of directly calling a method on an instance outside the scope of that instance then logically that method needs to be public.

Btw FB 4.6 compiler is provided by the used AIR/FLEX SDK and so cannot behave differently from FB 4.7 using the same SDK.

BotMaster
  • 2,233
  • 1
  • 13
  • 16
  • FlashBuilder 4.7 uses a new compiler (ASC 2.0) for "pure" ActionScript projects as the OP mentioned. So I do believe it is different. – Aaron Beall Feb 10 '15 at 17:33
  • That is not correct. FB 4.6/4.7 use AIR/FLEX SDKs. Those sdks provide the compilers or legacy compilers depending on their version. The used compiler has nothing to do with the FB version. Moreover the ASC2 is dropped in AIR 16 and useLegacyAOT is still available. All this can be run with FB 4.6 without any problem. – BotMaster Feb 10 '15 at 17:39
  • I believe that's correct for Flex projects, but not ActionScript projects. This is specifically mentioned in the ASC 2.0 release notes: "**This is the same compiler that is included with Flash Builder® 4.7**" (OP mentioned FB version differences) ... "**ASC 2.0 supports compiling AS3 applications only.** While it exposes familiar mxmlc and compc command-line entry points, it does not support compiling Flex applications. ASC 2.0 replaces the legacy compiler entry points and is not supported as an overlay to a Flex SDK." – Aaron Beall Feb 10 '15 at 17:41
  • Switching them to public made the problem go away. It seems strange to me that the keyword `protected` would get handled this way (and disappointing). It was probably the "stricter adherence to the AS3 language specification" cited in Aaron's answer that broke it when it got ported over. – Panzercrisis Feb 10 '15 at 17:42
  • Aaron you are misunderstanding the docs. FB apps are just a shell, they use SDKs to work, those SDKs provide the compiler. OF course FB 4.7 was shipped with a newer SDks but nothing stops anybody to update the SDKs, AIR or FLEX on their FB 4.6 and get the exact same behavior. – BotMaster Feb 10 '15 at 17:44
  • I think this does make sense. If a member is `protected` but not referenced within the code being compiled, it considers it dead code. If it's `public`, it can't really know if it's dead-code because it could be used somewhere the compiler is not currently compiling. – Aaron Beall Feb 10 '15 at 17:44
  • Are you sure he was the one who did that? – Panzercrisis Feb 10 '15 at 17:49
  • Anyway I feel like the simple fix for the porting issue was in your answer, but the very root of it was in Aaron's answer. Y'all both deserve credit for this. – Panzercrisis Feb 10 '15 at 17:51
  • @BotMaster Sorry mate, I only down-voted because you said there is no difference between FB 4.6 and FB 4.7, when there definitely is. Of course if you use the same SDK and compilers in both, there is no difference. But the point is that FB 4.7 comes with a major new compiler that relates specifically to the OPs problem. FWIW I agree with your comments on scope, but that wasn't the OPs problem. – Aaron Beall Feb 10 '15 at 17:52
  • my answer says there's no difference when using the same SDK which is true. You down voted for no reason. – BotMaster Feb 10 '15 at 17:54
  • That's fair, you did say when "using the same SDK", but the issue here is that between FB 4.6 and FB 4.7 the OP was seeing a difference... your answer doesn't address that at all, and I would argue is misleading because there is a difference between FB 4.6 and 4.7 here, and its because of different compilers being used. (If it makes you feel any better I tried to un-down-vote you but it didn't let me.) – Aaron Beall Feb 10 '15 at 18:00
  • Seems logical but it's not. The PO will need to update his SDK anyway since for example you cannot publish any mobile project to the Apple store with an SDK below AIR/FLEX 16. – BotMaster Feb 10 '15 at 18:02
0

Flash Builder 4.7 uses ASC 2.0 to compile ActionScript projects. From the release notes, emphasis added:

ASC 2.0 is a new compiler for ActionScript® 3.0 (AS3). It has stricter adherence to the AS3 language specification, includes compilation performance improvements, is more stable under memory pressure, and contains some demonstration optimizations that can be optionally enabled (in-lining, dead code elimination).

I suspect that the compiler sees useSmallPortraitLayout() is not referenced in your original code, and is eliminated from the ABC output.

Aaron Beall
  • 49,769
  • 26
  • 85
  • 103
  • The compiler does not "miss" the method, it simply does not see it in its protected scope. This is a scope issue that is correctly reported by the compiler. Older compiler might have compiled the code "missing" that the method was out of scope. – BotMaster Feb 10 '15 at 18:00
  • I'm not sure if you do not understand how FB works or if you purposely want to ignore reality. If you set FB 4.7 with SDK 3.1 and FB 4.6 with SDK 3.4 then FB 4.6 will be the one behaving wrongly according to the PO findings. You understand that or not? – BotMaster Feb 10 '15 at 18:16
  • You need to chill out... I'm not saying the same SDK will behave differently in FB 4.6 vs FB 4.7, and that's not what the OP was asking about. The OP was asking why it behaved differently for him in FB 4.6 vs FB 4.7. The answer is ASC 2.0 shipped with FB 4.7 and not FB 4.6. In the OPs own words my answer was the "very root of it" so I'll leave it at that, not interested in a comment flame war. Thanks for the down-vote, hope it made *you* feel better. ;) – Aaron Beall Feb 10 '15 at 18:35