[FlexJS] more on undefined / non initialised values

classic Classic list List threaded Threaded
31 messages Options
12
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[FlexJS] more on undefined / non initialised values

Justin Mclean
Administrator
Hi,

So if you run this code on AS
public var s:String;
public var o:Object;
public var i:int;
public var n:Number;
public var b:Boolean;

public function init():void {
    trace(s);
    trace(o);
    trace(i);
    trace(n);
    trace(b);
}

You get:
null
null
0
NaN
false
null

but on JS you get:
undefined
undefined
0
undefined
undefined
undefined

Now with strings, objects and Arrays you can get issues with === and !== as they are null on one platform and undefined on an another - as discussed in the other thread.

But the issue is worse with Numbers and Booleans as there are additional concerns. Performance is also an issue as JS doesn't know what type they are and will be slowed down by implicit casting.

For example this code will not do as you expect and say b is true when it is not as undefined != false.

var b:Boolean;

if (b == false)
{
  trace(“b is false”);
}
else
{
  trace(“b is true”);
}

Luckily isNaN(undefined) returns true, NaN != undefined so that may cause some issues as well.

Thanks,
Justin
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [FlexJS] more on undefined / non initialised values

Josh Tynjala
Good points. I'm all for initializing more than we do now. Even if we don't
achieve parity with all types, Booleans should definitely default to false
and Numbers to NaN, if they aren't explicitly initialized with a value, in
my opinion.

- Josh

On Jun 3, 2017 7:27 PM, "Justin Mclean" <[hidden email]> wrote:

Hi,

So if you run this code on AS
public var s:String;
public var o:Object;
public var i:int;
public var n:Number;
public var b:Boolean;

public function init():void {
    trace(s);
    trace(o);
    trace(i);
    trace(n);
    trace(b);
}

You get:
null
null
0
NaN
false
null

but on JS you get:
undefined
undefined
0
undefined
undefined
undefined

Now with strings, objects and Arrays you can get issues with === and !== as
they are null on one platform and undefined on an another - as discussed in
the other thread.

But the issue is worse with Numbers and Booleans as there are additional
concerns. Performance is also an issue as JS doesn't know what type they
are and will be slowed down by implicit casting.

For example this code will not do as you expect and say b is true when it
is not as undefined != false.

var b:Boolean;

if (b == false)
{
  trace(“b is false”);
}
else
{
  trace(“b is true”);
}

Luckily isNaN(undefined) returns true, NaN != undefined so that may cause
some issues as well.

Thanks,
Justin
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [FlexJS] more on undefined / non initialised values

Alex Harui-2
Sounds like there is no one right answer, so we should offer choices in
compiler output.

To me, if there are valid and common AS coding patterns that don't require
initialization, I would happily use them and make changes where warnings
detect unsafe usage.

IOW, for

var b:Boolean;

I believe in AS, there is no way to have

        if (b === false)

Have any semantically different meaning than

        if (b)

This latter pattern is fastest and smallest.  If we ever add optimizing to
the compiler, it might the first pattern to the latter.

IMO, we are not here to be able to reproduce every line of JS ever written
by writing AS, we are purposefully limiting the kinds of JS you can write
by making you use AS, so you don't screw yourself over and have improved
developer productivity.  We won't let you assign types that mismatch, or
have the wrong number of parameters.

So once you agree that we only want to support AS semantics in JS, then we
can see where we must initialize, and where we might want to offer options.

My 2 cents,
-Alex

On 6/4/17, 6:38 PM, "Josh Tynjala" <[hidden email]> wrote:

>Good points. I'm all for initializing more than we do now. Even if we
>don't
>achieve parity with all types, Booleans should definitely default to false
>and Numbers to NaN, if they aren't explicitly initialized with a value, in
>my opinion.
>
>- Josh
>
>On Jun 3, 2017 7:27 PM, "Justin Mclean" <[hidden email]> wrote:
>
>Hi,
>
>So if you run this code on AS
>public var s:String;
>public var o:Object;
>public var i:int;
>public var n:Number;
>public var b:Boolean;
>
>public function init():void {
>    trace(s);
>    trace(o);
>    trace(i);
>    trace(n);
>    trace(b);
>}
>
>You get:
>null
>null
>0
>NaN
>false
>null
>
>but on JS you get:
>undefined
>undefined
>0
>undefined
>undefined
>undefined
>
>Now with strings, objects and Arrays you can get issues with === and !==
>as
>they are null on one platform and undefined on an another - as discussed
>in
>the other thread.
>
>But the issue is worse with Numbers and Booleans as there are additional
>concerns. Performance is also an issue as JS doesn't know what type they
>are and will be slowed down by implicit casting.
>
>For example this code will not do as you expect and say b is true when it
>is not as undefined != false.
>
>var b:Boolean;
>
>if (b == false)
>{
>  trace(“b is false”);
>}
>else
>{
>  trace(“b is true”);
>}
>
>Luckily isNaN(undefined) returns true, NaN != undefined so that may cause
>some issues as well.
>
>Thanks,
>Justin

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [FlexJS] more on undefined / non initialised values

Justin Mclean
Administrator
Hi,

> I believe in AS, there is no way to have
>
> if (b === false)
>
> Have any semantically different meaning than
>
>       if (b)

One will check for false the other true so they have opposite meaning. You'll also note I stated “b == false” not “b === false”.

Currently for an uninitialised variable b == false will equal true on AS but false on JS

> This latter pattern is fastest and smallest.  If we ever add optimizing to
> the compiler, it might the first pattern to the latter.

I hope not as it will produce a lot of errors.

You’ll also need to consider b == condition where the condition evaluates to false but b is undefined, again you will get the result of true on AS and false on JS.

Thanks,
Justin
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [FlexJS] more on undefined / non initialised values

Justin Mclean
Administrator
In reply to this post by Josh Tynjala
Hi,

>  Booleans should definitely default to false and Numbers to NaN, if they aren't explicitly initialized with a value

Anyone have a differing option?

Thanks,
Justin
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [FlexJS] more on undefined / non initialised values

piotrz
Agree with this two, as for the rest I would not touch them.

Piotr
Apache Flex PMC
piotrzarzycki21@gmail.com
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [FlexJS] more on undefined / non initialised values

Alex Harui-2
In reply to this post by Justin Mclean
It sounds like there are differing opinions.  Some folks want all booleans
to be initialized to false, just in case someone uses a pattern like:

  if (someBoolean === false)

I would rather find where I've written that pattern so I can manually
change it to:

  if (!someBoolean)

since there is no semantic difference in AS.  And then I can avoid the
expense of initializing boolean variables.

We don't have to agree.  We can teach the compiler to do both.

-Alex


On 6/7/17, 5:23 PM, "Justin Mclean" <[hidden email]> wrote:

>Hi,
>
>>  Booleans should definitely default to false and Numbers to NaN, if
>>they aren't explicitly initialized with a value
>
>Anyone have a differing option?
>
>Thanks,
>Justin

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [FlexJS] more on undefined / non initialised values

Justin Mclean
Administrator
Hi,

>  if (someBoolean === false)

II think you may be missing the point? The issue is with:

if (someBoolean == false)

Not:

if (someBoolean === false)

Thanks,
Justin
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [FlexJS] more on undefined / non initialised values

Justin Mclean
Administrator
Hi,

Also how wold you fix this?

if (someBoolean == (complex expression that equals false))

Thanks,
Justin
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [FlexJS] more on undefined / non initialised values

Harbs
In reply to this post by Justin Mclean
I’m probably missing the point too.

Since an uninitialize boolean would be undefined, undefined == false, so that’s okay.
undefined !== false, so that’s not okay.

Oh. One sec. I actually just tried it in JS and I see that undefined != false. That’s weird. I don’t think I ever realized this (or I forgot it long ago)

so:
var a;
if(a) // is falsy
if(a==true)//falsy
but:
if(a==false)//also falsy

Harbs

> On Jun 9, 2017, at 1:12 AM, Justin Mclean <[hidden email]> wrote:
>
> Hi,
>
>> if (someBoolean === false)
>
> II think you may be missing the point? The issue is with:
>
> if (someBoolean == false)
>
> Not:
>
> if (someBoolean === false)
>
> Thanks,
> Justin

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [FlexJS] more on undefined / non initialised values

Justin Mclean
Administrator
HI,

> Oh. One sec. I actually just tried it in JS and I see that undefined != false. That’s weird.

Yep that’s the issue.

Thanks,
Justin
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [FlexJS] more on undefined / non initialised values

Alex Harui-2
Thanks for pointing it was == and not ===, but I must still be missing
something.  If a variable is of type Boolean in AS (not JS), is there a
difference between these three patterns:

If (b)
If (b == true)
If (b === true)

Or these three?

If (!b)
If (b == false)
If (b === false)

I don't think there is, and so for me, I would rather not have the output
JS initialize b to false and would rather have the compiler catch were I
wrote anything other than (b) or (!b).  I'd happily replace them and save
code.

But again, I don't think we have to agree.  The compiler can be taught to
respond to options to initialize everything as well detect unnecessary
code.

Thanks,
-Alex

On 6/8/17, 3:40 PM, "Justin Mclean" <[hidden email]> wrote:

>HI,
>
>> Oh. One sec. I actually just tried it in JS and I see that undefined !=
>>false. That’s weird.
>
>Yep that’s the issue.
>
>Thanks,
>Justin

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [FlexJS] more on undefined / non initialised values

Josh Tynjala
I suspect that the if(b == true) and if(b == false) patterns aren't out of
the ordinary in real-world code. I hope the default will be to initialize
Booleans to false and that you'll need to opt into the other behavior.

- Josh

On Fri, Jun 9, 2017 at 3:38 PM, Alex Harui <[hidden email]> wrote:

> Thanks for pointing it was == and not ===, but I must still be missing
> something.  If a variable is of type Boolean in AS (not JS), is there a
> difference between these three patterns:
>
> If (b)
> If (b == true)
> If (b === true)
>
> Or these three?
>
> If (!b)
> If (b == false)
> If (b === false)
>
> I don't think there is, and so for me, I would rather not have the output
> JS initialize b to false and would rather have the compiler catch were I
> wrote anything other than (b) or (!b).  I'd happily replace them and save
> code.
>
> But again, I don't think we have to agree.  The compiler can be taught to
> respond to options to initialize everything as well detect unnecessary
> code.
>
> Thanks,
> -Alex
>
> On 6/8/17, 3:40 PM, "Justin Mclean" <[hidden email]> wrote:
>
> >HI,
> >
> >> Oh. One sec. I actually just tried it in JS and I see that undefined !=
> >>false. That’s weird.
> >
> >Yep that’s the issue.
> >
> >Thanks,
> >Justin
>
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [FlexJS] more on undefined / non initialised values

Justin Mclean
Administrator
In reply to this post by Alex Harui-2
Hi,

> If a variable is of type Boolean in AS (not JS), is there a
> difference between these three patterns.

No as a boolean can only have the values of true and false and defaults to false in AS.

If you take the same code and run it in the browser it can now have three values, true, false and undefined and it defaults to undefined.

Currently this is cause bugs as undefined != false in JS.

For example this program with incorrectly get "B is true” in the browser and “B is false” in the flash player.

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

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

   <fx:Script><![CDATA[
           protected function init():void
           {
               var b:Boolean;

               if (b == false) {
                   trace("B is false");
               }
               else {
                   trace("B is true");
               }
           }
       ]]></fx:Script>

   <js:initialView>
       <js:View percentWidth="100" percentHeight="100">
       </js:View>
   </js:initialView>

</js:Application>

It is however a simple example and the same issue will also occur in any case where you end up comparing a freshly defined boolean (i.e. undefined) with an expression that evaluates to false so just converting (b == false) to (!b) would not be enough to solve the issue.

Thanks,
Justin
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [FlexJS] more on undefined / non initialised values

Justin Mclean
Administrator
Hi,

And this particular rabbit hole goes a lot deeper.

Any guesses what these two expression give?
false && undefined
undefined && false

If you expect them to have the same answer you would be incorrect.

Does this matter? Well try this code on both platforms:

var a:Boolean;
var b:Boolean = false;
var c:Boolean = false;

if ((a && b) != c) {
    trace("True");
}
else {
    trace(“False);
}

You’ll get “False” in the flash player and “True” in JS.

And again this is a simple example the RHS would be a much more complex expression that equates to false and you’ll still have this bug.

Thanks,
Justin
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [FlexJS] more on undefined / non initialised values

Alex Harui-2
In reply to this post by Justin Mclean
The general principle is optimization.  Optimization looks for specific
patterns.  What you wrote below is not one of the patterns.  Would be fun
to see how often that pattern exists though.  IMO, it would not make sense
to initialize every boolean because 1% of the boolean expressions require
optimization if alternative patterns exist that allow for smaller code.

But again, we don't have to agree, just provide compiler options.

-Alex


On 6/8/17, 3:17 PM, "Justin Mclean" <[hidden email]> wrote:

>Hi,
>
>Also how wold you fix this?
>
>if (someBoolean == (complex expression that equals false))
>
>Thanks,
>Justin

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [FlexJS] more on undefined / non initialised values

Justin Mclean
Administrator
HI,

> The general principle is optimization.  Optimization looks for specific
> patterns.  What you wrote below is not one of the patterns.

Not one of what patterns?

BTW Initialising the Boolean to false also optimises the seed by a factor of two. i.e. twice as fast.

> Would be fun to see how often that pattern exists though.

From a quick glance  (not testing)it exists in serval places in the existing SDK.

Thanks,
Justin
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [FlexJS] more on undefined / non initialised values

Justin Mclean
Administrator
Hi,

I think we may be talking cross purposes here to be clear - IMO this is not an optimisation issue this it’s a serious bug.

Justin
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [FlexJS] more on undefined / non initialised values

Josh Tynjala
I agree that this is a serious bug.

- Josh

On Jun 9, 2017 10:49 PM, <[hidden email]> wrote:

> Hi,
>
> I think we may be talking cross purposes here to be clear - IMO this is
> not an optimisation issue this it’s a serious bug.
>
> Justin
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [FlexJS] more on undefined / non initialised values

Justin Mclean
Administrator
Hi,

So to summarise this thread.
- discussing if Boolean be initialised to false and Numbers to NaN
- Code can act differently on AS and JS when these initialisers are not present
- Josh and I think this a serious bug
- Harbs also sees the issue
- Piotrz also wants Booleans and Numbers to be initialised
-  Alex thinks this is an optimisation issue

I’ve went ahead and made the change and checked into a new initialization branch of falcon.

Testing with a real world application gave no notable size increase and improved performance by 10% on JS. Mostly I would guess due to use of == and != in the framework and implicit casting that goes on when when comparing uninitialised variables.

Thanks,
Justin
12
Loading...