Release version acting different to debug version

classic Classic list List threaded Threaded
18 messages Options
Reply | Threaded
Open this post in threaded view
|

Release version acting different to debug version

Justin Mclean
Hi,

This simple example that makes JSON call and displays the results:

<?xml version="1.0" encoding="utf-8"?>
<js:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
                xmlns:js="library://ns.apache.org/royale/basic"
                applicationComplete="callSever()">

    <js:beads>
        <js:ApplicationDataBinding />
    </js:beads>

    <fx:Script><![CDATA[        
        import org.apache.royale.events.Event;
        import org.apache.royale.net.HTTPConstants;
        import org.apache.royale.net.HTTPService;

        protected var service:HTTPService;

        [Bindable] protected var description:String;
        [Bindable] protected var homepage:String;

        public function callSever():void {
            service = new HTTPService();
            service.url = "https://projects.apache.org/json/projects/flex.json";
            service.method = HTTPConstants.POST;
            service.addEventListener(Event.COMPLETE, projectInfo);
            service.send();
        }

        public function projectInfo(event:Event):void {
            var info:Object = JSON.parse(service.data);
            var status:int = service.status;

            if (status == 200) {
                description = info.shortdesc;
                homepage = info.homepage;
            }
            service.removeEventListener(Event.COMPLETE, projectInfo);
            service = null;
        }
        ]]></fx:Script>

    <js:valuesImpl>
        <js:SimpleCSSValuesImpl/>
    </js:valuesImpl>

    <js:initialView>
        <js:View>
            <js:VContainer>
                <js:Label text="Project info" />
                <js:MultilineLabel text="{description}" width="500" />
                <js:Label text="{homepage}" />
            </js:VContainer>
        </js:View>
    </js:initialView>

</js:Application>


Works as expected in debug and displays:
Project info
Apache Flex® is a highly productive, open source application framework for building and maintaining expressive web applications that deploy consistently on all major browsers, desktops and devices (including smartphones, tablets and tv).
http://flex.apache.org

The release version however displays:
Project info
undefined
http://flex.apache.org

In both case the JSON is correctly asked for and returned. A console.log(info.shortdesc); gives undefined in the production version but console.log(info[“shortdesc”]) works. Is this a known issue? Is seems odd that homepage works while shortdesc doesn’t.

Thanks,
Justin


Reply | Threaded
Open this post in threaded view
|

Re: Release version acting different to debug version

Olaf Krueger
Justin Mclean wrote
> Is seems odd that homepage works while shortdesc doesn’t.

Maybe there's something inside the 'homepage' string which causes the issue?
Do you've tried to remove the ® from the string to see what happens?

Olaf




--
Sent from: http://apache-royale-users.20374.n8.nabble.com/
Reply | Threaded
Open this post in threaded view
|

Re: Release version acting different to debug version

Justin Mclean
Hi,

> Maybe there's something inside the 'homepage' string which causes the issue?
> Do you've tried to remove the ® from the string to see what happens?

It looks to be how the code is optimised i.e. one of the variables is being renamed to something shorter and thus it cannot find the field but the other variable isn’t. I guess homepage is is used in a slightly more complex so may not be optimised.

Either way something to look out for when consuming JSON.

Thanks,
Justin
Reply | Threaded
Open this post in threaded view
|

Re: Release version acting different to debug version

Gabe Harbs
In reply to this post by Justin Mclean
Yes. This is something I discussed in my “migrating” talk.

It’s a limitation with the Google compiler. Any untyped objects can be renamed.

There are two ways to deal with this.

The first is to use bracket notation on untyped objects.
The second is to only use typed objects.

Harbs

> On Nov 27, 2017, at 5:33 AM, Justin Mclean <[hidden email]> wrote:
>
> Hi,
>
> This simple example that makes JSON call and displays the results:
>
> <?xml version="1.0" encoding="utf-8"?>
> <js:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
>                xmlns:js="library://ns.apache.org/royale/basic"
>                applicationComplete="callSever()">
>
>    <js:beads>
>        <js:ApplicationDataBinding />
>    </js:beads>
>
>    <fx:Script><![CDATA[        
>        import org.apache.royale.events.Event;
>        import org.apache.royale.net.HTTPConstants;
>        import org.apache.royale.net.HTTPService;
>
>        protected var service:HTTPService;
>
>        [Bindable] protected var description:String;
>        [Bindable] protected var homepage:String;
>
>        public function callSever():void {
>            service = new HTTPService();
>            service.url = "https://projects.apache.org/json/projects/flex.json";
>            service.method = HTTPConstants.POST;
>            service.addEventListener(Event.COMPLETE, projectInfo);
>            service.send();
>        }
>
>        public function projectInfo(event:Event):void {
>            var info:Object = JSON.parse(service.data);
>            var status:int = service.status;
>
>            if (status == 200) {
>                description = info.shortdesc;
>                homepage = info.homepage;
>            }
>            service.removeEventListener(Event.COMPLETE, projectInfo);
>            service = null;
>        }
>        ]]></fx:Script>
>
>    <js:valuesImpl>
>        <js:SimpleCSSValuesImpl/>
>    </js:valuesImpl>
>
>    <js:initialView>
>        <js:View>
>            <js:VContainer>
>                <js:Label text="Project info" />
>                <js:MultilineLabel text="{description}" width="500" />
>                <js:Label text="{homepage}" />
>            </js:VContainer>
>        </js:View>
>    </js:initialView>
>
> </js:Application>
>
>
> Works as expected in debug and displays:
> Project info
> Apache Flex® is a highly productive, open source application framework for building and maintaining expressive web applications that deploy consistently on all major browsers, desktops and devices (including smartphones, tablets and tv).
> http://flex.apache.org
>
> The release version however displays:
> Project info
> undefined
> http://flex.apache.org
>
> In both case the JSON is correctly asked for and returned. A console.log(info.shortdesc); gives undefined in the production version but console.log(info[“shortdesc”]) works. Is this a known issue? Is seems odd that homepage works while shortdesc doesn’t.
>
> Thanks,
> Justin
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Release version acting different to debug version

Olaf Krueger
In reply to this post by Justin Mclean
Which FlexJS/Royale version do you use?
I remember that this worked for me with FlexJS 0.8.0 [1].
(I will check it out soon with the latest snapshot version).

[1]
                        private function onResult(result:Event):void {
                                var jsonResult:Object = JSON.parse(result.target.data as String) as
Object;
                               
                                // Populate iframe
                                this.addIframe(jsonResult.projectUrl);

                                // Populate console with compiler output
                                this.tiConsole.text = jsonResult.compilerOutput;
                        }
 



--
Sent from: http://apache-royale-users.20374.n8.nabble.com/
Reply | Threaded
Open this post in threaded view
|

Re: Release version acting different to debug version

Gabe Harbs
No. That will likely be minified in the release version and you’ll get something like:

> var f = JSON.parse(result.target.data);

> this.addIframe(f.a);
> this.tiConsole.text = f.b;

This has been an issue for as long as I can remember.

Harbs

> On Nov 27, 2017, at 9:22 AM, Olaf Krueger <[hidden email]> wrote:
>
> Which FlexJS/Royale version do you use?
> I remember that this worked for me with FlexJS 0.8.0 [1].
> (I will check it out soon with the latest snapshot version).
>
> [1]
> private function onResult(result:Event):void {
> var jsonResult:Object = JSON.parse(result.target.data as String) as
> Object;
>
> // Populate iframe
> this.addIframe(jsonResult.projectUrl);
>
> // Populate console with compiler output
> this.tiConsole.text = jsonResult.compilerOutput;
> }
>
>
>
>
> --
> Sent from: http://apache-royale-users.20374.n8.nabble.com/

Reply | Threaded
Open this post in threaded view
|

Re: Release version acting different to debug version

Justin Mclean
In reply to this post by Olaf Krueger
HI,

> Which FlexJS/Royale version do you use?

Latest developer branch version as I compile locally.

> I remember that this worked for me with FlexJS 0.8.0 [1].

Did you try both debug and release versions? It would work fine in debug but not release would be my guess - but you might be lucky and not have the variables renamed.

Thanks,
Justin
Reply | Threaded
Open this post in threaded view
|

Re: Release version acting different to debug version

Olaf Krueger
>Did you try both debug and release versions?
I probably remember it wrong so sorry for the confusion!
I didn't notice Harbs post before posting, I guess Harbs knows what's going
on.
We should put it to the Royale docs ;-)

I'll try to continue the work with the docs after I finished the
"Try-it-now" stuff which I am currently working on.

Thanks,
Olaf





--
Sent from: http://apache-royale-users.20374.n8.nabble.com/
Reply | Threaded
Open this post in threaded view
|

Re: Release version acting different to debug version

Piotr Zarzycki
+1 for your doc work! :) 

Thanks, Piotr

2017-11-27 8:43 GMT+01:00 Olaf Krueger <[hidden email]>:
>Did you try both debug and release versions?
I probably remember it wrong so sorry for the confusion!
I didn't notice Harbs post before posting, I guess Harbs knows what's going
on.
We should put it to the Royale docs ;-)

I'll try to continue the work with the docs after I finished the
"Try-it-now" stuff which I am currently working on.

Thanks,
Olaf



--

Piotr Zarzycki 

Patreon: https://www.patreon.com/piotrzarzycki

Reply | Threaded
Open this post in threaded view
|

Re: Release version acting different to debug version

Justin Mclean
In reply to this post by Gabe Harbs
Hi,

> It’s a limitation with the Google compiler. Any untyped objects can be renamed.

Which with JSON is just about always going to be.

I wonder if we can use dynamic classes to get around this?

I just tried:
package {
public dynamic class ReturnedJSON {
    public function ReturnedJSON(obj:Object) {
        for (var field:String in obj) {
           this[field] = obj[field];
        }
    }
}
}

var info:ReturnedJSON = new ReturnedJSON(JSON.parse(service.data));

Which didn’t work (same issue as before) so it seems it's a little more than just plain objects that have this issue?


This on the other hand does work and is probably a nice way to encapsulate the issue as you can use dot notation and get type safety outside the class.

package {
public class ReturnedJSON {

    public var description:String;
    public var homepage:String;

    public function ReturnedJSON(obj:Object) {
        for (var field:String in obj) {
            description = obj["description"];
            homepage = obj["sitename"];
        }
    }
}
}

Thanks,
Justin
Reply | Threaded
Open this post in threaded view
|

Re: Release version acting different to debug version

Gabe Harbs
> Which didn’t work (same issue as before) so it seems it's a little more than just plain objects that have this issue?

No. Same problem. The problem is with the setting of the properties. When you then get the properties, the properties are renamed and undefined.

> This on the other hand does work and is probably a nice way to encapsulate the issue as you can use dot notation and get type safety outside the class.

Yes. It works (and I’ve used this pattern, but kind of annoying if you ask me.

The best way to handle it is probably to define interfaces with getters and setter of the properties. Something like this will likely work, but I have never taken the time to test:

package
        public interface JsonResponse
        {
                function get shortdesc():String;
                function get homepage():String;
                function set shortdesc(value:String):void;
                function set homepage(value:String):void;
        }
}
           var info:JsonResponse = JSON.parse(service.data);
           var status:int = service.status;

           if (status == 200) {
               description = info.shortdesc;
               homepage = info.homepage;
           }
           service.removeEventListener(Event.COMPLETE, projectInfo);
           service = null;
       }

I would be interested in knowing if it does work.

Harbs

> On Nov 27, 2017, at 10:05 AM, Justin Mclean <[hidden email]> wrote:
>
> Hi,
>
>> It’s a limitation with the Google compiler. Any untyped objects can be renamed.
>
> Which with JSON is just about always going to be.
>
> I wonder if we can use dynamic classes to get around this?
>
> I just tried:
> package {
> public dynamic class ReturnedJSON {
>    public function ReturnedJSON(obj:Object) {
>        for (var field:String in obj) {
>           this[field] = obj[field];
>        }
>    }
> }
> }
>
> var info:ReturnedJSON = new ReturnedJSON(JSON.parse(service.data));
>
> Which didn’t work (same issue as before) so it seems it's a little more than just plain objects that have this issue?
>
>
> This on the other hand does work and is probably a nice way to encapsulate the issue as you can use dot notation and get type safety outside the class.
>
> package {
> public class ReturnedJSON {
>
>    public var description:String;
>    public var homepage:String;
>
>    public function ReturnedJSON(obj:Object) {
>        for (var field:String in obj) {
>            description = obj["description"];
>            homepage = obj["sitename"];
>        }
>    }
> }
> }
>
> Thanks,
> Justin

Reply | Threaded
Open this post in threaded view
|

Re: Release version acting different to debug version

Olaf Krueger
In reply to this post by Justin Mclean
Justin Mclean wrote

> This on the other hand does work and is probably a nice way to encapsulate
> the issue as you can use dot notation and get type safety outside the
> class.
>
> package {
> public class ReturnedJSON {
>
>     public var description:String;
>     public var homepage:String;
>
>     public function ReturnedJSON(obj:Object) {
>         for (var field:String in obj) {
>             description = obj["description"];
>             homepage = obj["sitename"];
>         }
>     }
> }
> }

I guess you forgot to remove the loop!?:

    public function ReturnedJSON(obj:Object) {
            description = obj["description"];
            homepage = obj["sitename"];
    }


With classic Flex I usually implement a 'fromJSON' method within my VOs to
convert JSON to typed objects/VOs.
It's some additional manual work and maybe annoying but it just works and
you have full control of how to convert the JSON:

public class MyVO {

  public var foo:String;
  public var bar:String;

  public static function fromJSON(json:Object):MyVO {
     
    var myVO:MyVO = new MyVO();
    myVO.foo = json["foo"];
    myVO.bar = json["bar"];
   
    return myVO;
  }
}





--
Sent from: http://apache-royale-users.20374.n8.nabble.com/
Reply | Threaded
Open this post in threaded view
|

Re: Release version acting different to debug version

Justin Mclean
Hi,

> I guess you forgot to remove the loop!?:
>
>    public function ReturnedJSON(obj:Object) {
>            description = obj["description"];
>            homepage = obj["sitename"];
>    }

Yep copy and paste error sorry.

Thanks,
Justin
Reply | Threaded
Open this post in threaded view
|

Re: Release version acting different to debug version

Justin Mclean
In reply to this post by Gabe Harbs
Hi,

> No. Same problem. The problem is with the setting of the properties. When you then get the properties, the properties are renamed and undefined.

So the issue with the properties of any class not just those of type “Object”.

> Yes. It works (and I’ve used this pattern, but kind of annoying if you ask me.

Yep a little.

> The best way to handle it is probably to define interfaces with getters and setter of the properties. Something like this will likely work, but I have never taken the time to test:
<snip>
> I would be interested in knowing if it does work.

It fails to compile and if you add “as JsonResponse” it compiles but y ou end up with info being set to null so sorry that doesn’t work either.

Thanks,
Justin
Reply | Threaded
Open this post in threaded view
|

Re: Release version acting different to debug version

Gabe Harbs

> On Nov 27, 2017, at 10:39 AM, Justin Mclean <[hidden email]> wrote:
>
> Hi,
>
>> No. Same problem. The problem is with the setting of the properties. When you then get the properties, the properties are renamed and undefined.
>
> So the issue with the properties of any class not just those of type “Object”.

Normal classes are not a problem because it’s renamed consistently everywhere. If you care about what the properties are actually called, then you are right that it will be a problem.

>> Yes. It works (and I’ve used this pattern, but kind of annoying if you ask me.
>
> Yep a little.
>
>> The best way to handle it is probably to define interfaces with getters and setter of the properties. Something like this will likely work, but I have never taken the time to test:
> <snip>
>> I would be interested in knowing if it does work.
>
> It fails to compile and if you add “as JsonResponse” it compiles but y ou end up with info being set to null so sorry that doesn’t work either.

Use ignore as coercions.

> Thanks,
> Justin

Reply | Threaded
Open this post in threaded view
|

Re: Release version acting different to debug version

Justin Mclean
Hi,

> Use ignore as coercions.

I assume you mean like so:

/*
 *@royaleignorecoercion ReturnedJSON
 */
public function projectInfo(event:Event):void {
    var info:ReturnedJSON = JSON.parse(service.data);

(where ReturnedJSON is the suggested interface)

That fails to compile with:
Implicit coercion of a value with static type Object to a possibly unrelated type ReturnedJSON.

Adding “as ReturnedJSON” makes it compile (like before) but info again info ends up being null.

Thanks for the suggestions but think we’re back to square one here.
 
Thanks,
Justin
Reply | Threaded
Open this post in threaded view
|

Re: Release version acting different to debug version

Gabe Harbs
You need `var info:ReturnedJSON = JSON.parse(service.data) as ReturnedJSON;`

There’s two ways to ignore coercion. One is by using the comment, the second is using the compiler option for the whole project.

> On Nov 27, 2017, at 10:58 AM, Justin Mclean <[hidden email]> wrote:
>
> Hi,
>
>> Use ignore as coercions.
>
> I assume you mean like so:
>
> /*
> *@royaleignorecoercion ReturnedJSON
> */
> public function projectInfo(event:Event):void {
>    var info:ReturnedJSON = JSON.parse(service.data);
>
> (where ReturnedJSON is the suggested interface)
>
> That fails to compile with:
> Implicit coercion of a value with static type Object to a possibly unrelated type ReturnedJSON.
>
> Adding “as ReturnedJSON” makes it compile (like before) but info again info ends up being null.
>
> Thanks for the suggestions but think we’re back to square one here.
>
> Thanks,
> Justin

Reply | Threaded
Open this post in threaded view
|

Re: Release version acting different to debug version

Justin Mclean
Hi,

> You need `var info:ReturnedJSON = JSON.parse(service.data) as ReturnedJSON;`


As I said I tried this and info ends up as null so that doesn’t work.

Thanks,
Justin