Private properties are undefined in JS and null in AS

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

Private properties are undefined in JS and null in AS

Justin Mclean
Administrator
Hi,

This code:

private var a:Object;

protected function init():void
{
    trace(a);
}

When init() is called with display “null” in when run the FlashPlayer and display “undefined” when compiled into JS and run in a browser.

How should we fix this?

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

Re: Private properties are undefined in JS and null in AS

Justin Mclean
Administrator
Hi,

Also the same for public and protected so at least it's consistence in it’s inconsistency :-)

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

Re: Private properties are undefined in JS and null in AS

Josh Tynjala
In reply to this post by Justin Mclean
I just mentioned the same thing in response to your other thread.

Defaulting to null (where appropriate) would help, I think. However, later
assignments can still cause a variable to be set to undefined in JS but
null in SWF. That could be considered a separate issue, but it's definitely
related.

- Josh

On Jun 2, 2017 6:55 PM, "Justin Mclean" <[hidden email]> wrote:

> Hi,
>
> This code:
>
> private var a:Object;
>
> protected function init():void
> {
>     trace(a);
> }
>
> When init() is called with display “null” in when run the FlashPlayer and
> display “undefined” when compiled into JS and run in a browser.
>
> How should we fix this?
>
> Thanks,
> Justin
Reply | Threaded
Open this post in threaded view
|

Re: Private properties are undefined in JS and null in AS

Alex Harui-2
As Josh mentioned in the other thread, we need data.  Maybe there isn't a
right answer and folks will have to use directives or compiler options to
get what they want for their needs.

The data probably needs to answer at least the following questions:

1) how much slower is === than == (and similarly !== vs !=) in AS and JS?
I think you'd have to test for different types and maybe values.  I don't
have time to look for the code, maybe somebody can find it in Tamarin, but
I seem to recall that certain types and values did a lot of implicit
coercions in "==" and "!=".
2) How much slower and fatter is initializing properties to null?


IIRC, in ActionScript, unless you are using "*", all other types cannot
have the value undefined, so most code never needed to worry about the
difference.  The vast majority of regular Flex SDK code just uses "==" and
"!=".

AIUI, in JavaScript, the same code for types that are not "*" that tests
with "==" and "!=" will "just work".  If the code uses "===" or "!==" will
it be that much faster if we have to stop and initialize EVERY
uninitialized property to null?  We might be able to be smart and
initialize local variables to null if the method body is using "===" but
again, is it worth it?

For "*", I believe we are emitting ES5 and/or only supporting browsers
that run ES5, so I think that means that undefined cannot be redefined and
(typeof Foo === 'undefined') isn't necessary.  Others should very this.

We could also warn on use of '===' and '!==' when null or undefined is
involved.

My 2 cents,
-Alex


On 6/2/17, 9:14 PM, "Josh Tynjala" <[hidden email]> wrote:

>I just mentioned the same thing in response to your other thread.
>
>Defaulting to null (where appropriate) would help, I think. However, later
>assignments can still cause a variable to be set to undefined in JS but
>null in SWF. That could be considered a separate issue, but it's
>definitely
>related.
>
>- Josh
>
>On Jun 2, 2017 6:55 PM, "Justin Mclean" <[hidden email]> wrote:
>
>> Hi,
>>
>> This code:
>>
>> private var a:Object;
>>
>> protected function init():void
>> {
>>     trace(a);
>> }
>>
>> When init() is called with display “null” in when run the FlashPlayer
>>and
>> display “undefined” when compiled into JS and run in a browser.
>>
>> How should we fix this?
>>
>> Thanks,
>> Justin

Reply | Threaded
Open this post in threaded view
|

Re: Private properties are undefined in JS and null in AS

piotrz
Hi,

I would be really interested to have answer to each of this questions. It can give us answer what actually need to be used.

I would suggest till then do not change anything - apart of obvious bugs.

Piotr
Reply | Threaded
Open this post in threaded view
|

Re: Private properties are undefined in JS and null in AS

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

> 1) how much slower is === than == (and similarly !== vs !=) in AS and JS?

In AS I don’t know but in JS in most browsers it’s in general 5-20% faster but does vary in what you are comparing.

> I seem to recall that certain types and values did a lot of implicit
> coercions in "==" and "!=“.

Yep and this can cause other issues as well. [1] == and != are often referred to as the evil twins. This in particular should give cause for alarm. [2] This for instance “ \n\n\n” == 0 is true!

Tools like JSLint and SonarCube encourage === and !== to be used. Most coding guidelines also prefer === and !==. [3]

> 2) How much slower and fatter is initializing properties to null?

Given it’s a one off and a comparison is likely to be made several time I would assume the cost of setting to null would be a lot lower.

> IIRC, in ActionScript, unless you are using "*", all other types cannot
> have the value undefined, so most code never needed to worry about the
> difference.  The vast majority of regular Flex SDK code just uses "==" and
> "!=“.

There’s a few edge cases that you do need to be concerned i.e. empty and not so empty strings that equate to false rather than true.

> For "*", I believe we are emitting ES5 and/or only supporting browsers
> that run ES5, so I think that means that undefined cannot be redefined and
> (typeof Foo === 'undefined') isn't necessary.

That’s my understanding as well.

Thanks,
Justin

1. https://stackoverflow.com/questions/359494/which-equals-operator-vs-should-be-used-in-javascript-comparisons <https://stackoverflow.com/questions/359494/which-equals-operator-vs-should-be-used-in-javascript-comparisons>
2. http://dorey.github.io/JavaScript-Equality-Table/ <http://dorey.github.io/JavaScript-Equality-Table/>
3. http://javascript.crockford.com/code.html <http://javascript.crockford.com/code.html>
Reply | Threaded
Open this post in threaded view
|

Re: Private properties are undefined in JS and null in AS

piotrz
Justin,

Do you find cycles to perform some tests and present numbers?

Piotr
Reply | Threaded
Open this post in threaded view
|

Re: Private properties are undefined in JS and null in AS

Justin Mclean
Administrator
Hi,

> Do you find cycles to perform some tests and present numbers?

There are existing tests out there see for example JSPerf.com [1]

For instance on Safari != vs !== and == vs === is 99% slower (yikes!) when comparing different types. Chrome give similar results.

Now hopefully most comparison are between the same types so I’m not expecting order of magnitude difference in perfomrance.

The changes I made to recently gave a 250% speed increase for our application as profiled in Chrome. So I think this is certainly something to seriously consider SDK wide.

Thanks,
Justin

1. https://jsperf.com/triple-equals-vs-double-equals/3
Reply | Threaded
Open this post in threaded view
|

Re: Private properties are undefined in JS and null in AS

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


On 6/2/17, 11:59 PM, "Justin Mclean" <[hidden email]> wrote:
>
>> 2) How much slower and fatter is initializing properties to null?
>
>Given it’s a one off and a comparison is likely to be made several time I
>would assume the cost of setting to null would be a lot lower.

I'm not sure it is always one-off.  I think every function call will need
to initialize its local variables.  But even a couple of thousand
initializations at startup might make download size and startup time a
factor.  So the data would probably need to measure how many new
initializations the framework would have to have.

Also, we have to remember that the final optimization is done by Google
and not us.  We are type annotating the output and they and/or the browser
runtimes may also someday optimize and auto convert "==" to "===" where it
can.  So it isn't clear to me that we have to manually go through and
replace our use of '=='.  I believe Flash's JIT also effectively auto
converts when it has sufficient type information.

Something the compiler could do is flag areas in the code where type
information is lacking.  That kind of thing may have greater impact on the
final performance.

-Alex


>

Reply | Threaded
Open this post in threaded view
|

Re: Private properties are undefined in JS and null in AS

Justin Mclean
Administrator
Hi,

> I'm not sure it is always one-off.  I think every function call will need
> to initialize its local variables.

Yep that may also need to be done in some cases.

> Also, we have to remember that the final optimization is done by Google
> and not us.  We are type annotating the output and they and/or the browser
> runtimes may also someday optimize and auto convert "==" to "===" where it
> can.

And it may do further optimisations where you use === rather than ==. Other than hyperticals do you have any data to show that it does this?

>  So it isn't clear to me that we have to manually go through and
> replace our use of '==‘.

In a real application making those changes in a small part of the code changed time spent sorting out css values from 30ms to 5ms. Can you explain why is that is not worth pursuing?

> Something the compiler could do is flag areas in the code where type
> information is lacking.  That kind of thing may have greater impact on the
> final performance.

It may or may not - do you have data showing this?

We have data that clearly shows === and !== are faster than their counterparts. Why would you not want to use them where it make sense?

I see if I can make some tests around setting to null so we have real data on that.

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

Re: Private properties are undefined in JS and null in AS

Justin Mclean
Administrator
Hi,

So here’s some data for you:

In string_old.js:

var s;

for (var i = 0; i < 1e8; i++) {
    if (s == "") {
    }
}

In string.js:

var s = "";

for (var i = 0; i < 1e8; i++) {
    if (s === "") {
    }
}

time node string.js
real 0m0.246s
user 0m0.114s
sys 0m0.046s

time node string_old.js
real 0m2.496s
user 0m2.452s
sys 0m0.019s

The === and setting to “" is an order of magnitude faster (in node anyway), similar results with initialising to null rather than “”.

Running similar code (converted to AS ) through the chrome profiler gives results where setting to null and using === is faster.

It even twice as fast if you initialise the variable and compare on every time through the loop. So 1e8 lots = null and a === is faster than no initialisation and a ==.

I think what is happening currently is that because we are not initialising the variable it’s doing a implicit cast on every every comparison that is very expensive when using != and ==, using === and !== significantly speeds this up but then you have the issues of uninitialise strings and objects being null in AS and undefined in JS but it still twice as fast.

BTW I do note that we are setting ints to 0. I assume because of similar reasons? But it seems you were not concerned with the overhead of this?

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

Re: Private properties are undefined in JS and null in AS

Alex Harui-2
Here is a link [1] to you saying "I’m a strong believer in getting it to
work first, then optimise it, premature optimisation wastes time and often
makes incorrect assumptions."

This is an interesting topic, but I want to make sure this isn't premature
optimizing.  And me, I just want to get it to work and get a release out.

IMO, the key to success for Flex is developer productivity.  Because we
have a couple of compilers in the workflow (FalconJX and Google Closure
Compiler), we have a couple of chances to make good small code that runs
well.  Manually trying to determine whether to use "==" or "===" might be
better left to tooling someday, so folks don't have to worry about it and
can just get their features to work first.  I don't want to tell folks,
"sorry, we don't have AMF support yet, but we've made sure we've used
strict equality!".

IMO, if folks can be more productive by using common patterns and we can
generate better code, then everybody wins.  I'd personally lean towards
warning when folks use JS patterns that can cause trouble.  JS lets you do
lots of things and the value undefined can get you in a lot of trouble,
but AS lets you do fewer things that can get you in trouble.  Undefined is
only allowed for type '*' for example.  So if we can know that a string
can't be null, then maybe the compiler should always generate "===" even
if you wrote "==".  For uninitialized references to instances, maybe
leaving it uninitialized and using "== null" is best.  Or maybe there
isn't a right answer and folks will want compiler options to generate
better code.  AS gives us real type information.

What is the point of initializing properties if there is a guarantee that
they'll be initialized in other code before it is ever tested.  Code like:

var foo:String;
if (someCondition)
  foo = "bar";
else
  foo = "foo";

Ints are initialized to zero because the common patterns fail if you
don't, not just because of "==" tests.

There are articles about JavaScript type inferencing in V8 and WebAssembly
is sort of implying something similar if I understand it correctly so type
"annotation" may eliminate some of the need to choose between "==" and
"===".

Sounds like the CSS code, which does use '*' could be improved by not
using "==" so much.  And that in many cases string compares can be faster
with "===".  That's great.  But there might be other ways to end up with
better code than manually scrubbing the source.

Of course, I could be wrong...
-Alex

[1]
http://mail-archives.apache.org/mod_mbox/flex-dev/201703.mbox/%3cDB1BB6CD-B
[hidden email]%3e

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

>Hi,
>
>So here’s some data for you:
>
>In string_old.js:
>
>var s;
>
>for (var i = 0; i < 1e8; i++) {
>    if (s == "") {
>    }
>}
>
>In string.js:
>
>var s = "";
>
>for (var i = 0; i < 1e8; i++) {
>    if (s === "") {
>    }
>}
>
>time node string.js
>real 0m0.246s
>user 0m0.114s
>sys 0m0.046s
>
>time node string_old.js
>real 0m2.496s
>user 0m2.452s
>sys 0m0.019s
>
>The === and setting to “" is an order of magnitude faster (in node
>anyway), similar results with initialising to null rather than “”.
>
>Running similar code (converted to AS ) through the chrome profiler gives
>results where setting to null and using === is faster.
>
>It even twice as fast if you initialise the variable and compare on every
>time through the loop. So 1e8 lots = null and a === is faster than no
>initialisation and a ==.
>
>I think what is happening currently is that because we are not
>initialising the variable it’s doing a implicit cast on every every
>comparison that is very expensive when using != and ==, using === and !==
>significantly speeds this up but then you have the issues of uninitialise
>strings and objects being null in AS and undefined in JS but it still
>twice as fast.
>
>BTW I do note that we are setting ints to 0. I assume because of similar
>reasons? But it seems you were not concerned with the overhead of this?
>
>Thanks,
>Justin

Reply | Threaded
Open this post in threaded view
|

Re: Private properties are undefined in JS and null in AS

piotrz
Well I like what Justin did in case of css and some other changes. It seems be performance improver, but please do not make changes more till people who has real world app like Harbs do not give some feedback whether there are not breaking changes.

From the developer point of view and as an more Flex developer than JavaScript I doubt that in my application code I will be remember about giving "===" almost every time. I will probably mostly use "==".

I'm waiting till release cause those changes are not for 0.8.0. Once we merge release branch to develop and have 0.9.0 I will test my real world app. - If it behave differently cause of this I will vote for revert.

Piotr
Reply | Threaded
Open this post in threaded view
|

Re: Private properties are undefined in JS and null in AS

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

> Here is a link [1] to you saying "I’m a strong believer in getting it to
> work first, then optimise it, premature optimisation wastes time and often
> makes incorrect assumptions.”

That’s exactly what I’m doing. I has something that works and I want to improve the performance.

I’d say making something working 5x as fast, with no other costs, is hardly premature optimisation. You’re milage of cause may vary.

> Manually trying to determine whether to use "==" or "===" might be
> better left to tooling someday, so folks don't have to worry about it and
> can just get their features to work first.

Folk will run into this issue right away. Most JS devs use == and !== and !== instead often evil twins != and ==.

The current behaviour will confuse people as code that works on JS will work differently in AS and vice versa.

> I'd personally lean towards warning when folks use JS patterns that can cause trouble.

What patterns in particular are you referring to here? Sonar cube is waring about issues in our AS code not JS code.

> For uninitialized references to instances, maybe
> leaving it uninitialized and using "== null" is best.

Unlikely as it’s between 2x and 10x as slow and using == null as opposed to === null can have unexpected results.

> What is the point of initializing properties if there is a guarantee that
> they'll be initialized in other code before it is ever tested.  Code like:
>
> var foo:String;
> if (someCondition)
> foo = "bar";
> else
> foo = "foo”;

Could be optimised away by the compiler.

> Ints are initialized to zero because the common patterns fail if you
> don't, not just because of "==" tests.

And I think we have the same issue with Booleans and perhaps Numbers.

> But there might be other ways to end up with
> better code than manually scrubbing the source.

Like what? Please provide data an/or examples and/or facts over option please.

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

Re: Private properties are undefined in JS and null in AS

Justin Mclean
Administrator
In reply to this post by piotrz
Hi,

> Well I like what Justin did in case of css and some other changes. It seems
> be performance improver, but please do not make changes more till people who
> has real world app like Harbs do not give some feedback whether there are
> not breaking changes.

I’m using a application in production and those changes are working fine for me.

Anyone else seen any issues with them? If there are any issues I’m happy to fix them.

If you use develop over the past couple of week you would of been using them.

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

Re: Private properties are undefined in JS and null in AS

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

>> What is the point of initializing properties if there is a guarantee that
>> they'll be initialized in other code before it is ever tested.  Code like:
>>
>> var foo:String;
>> if (someCondition)
>> foo = "bar";
>> else
>> foo = "foo”;
>
> Could be optimised away by the compiler.

And looks like this is currently likely.

For instance this code:

test = function() {
var foo = 'hello';
var cond = true;
if (cond)
 foo = 'bar';
else
 foo = 'foo';

 console.log(foo);
}
test();

Gets optimised to:
test=function(){console.log("bar")};test();

So there’s no cost in this case for the initial assignment and the variable doesn’t even exists in the final result. In more complex code you’ll probably get something different.

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

Re: Private properties are undefined in JS and null in AS

Josh Tynjala
In reply to this post by Justin Mclean
The release branch has diverged far enough from develop that I assume most
people aren't using develop until the release breach gets merged back in.

- Josh

On Jun 4, 2017 1:55 AM, "Justin Mclean" <[hidden email]> wrote:

> Hi,
>
> > Well I like what Justin did in case of css and some other changes. It
> seems
> > be performance improver, but please do not make changes more till people
> who
> > has real world app like Harbs do not give some feedback whether there are
> > not breaking changes.
>
> I’m using a application in production and those changes are working fine
> for me.
>
> Anyone else seen any issues with them? If there are any issues I’m happy
> to fix them.
>
> If you use develop over the past couple of week you would of been using
> them.
>
> Thanks,
> Justin
Reply | Threaded
Open this post in threaded view
|

Re: Private properties are undefined in JS and null in AS

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


On 6/4/17, 1:52 AM, "Justin Mclean" <[hidden email]> wrote:

>Hi,
>
>> Here is a link [1] to you saying "I’m a strong believer in getting it to
>> work first, then optimise it, premature optimisation wastes time and
>>often
>> makes incorrect assumptions.”
>
>That’s exactly what I’m doing. I has something that works and I want to
>improve the performance.
>
>I’d say making something working 5x as fast, with no other costs, is
>hardly premature optimisation. You’re milage of cause may vary.

I think everyone is supporting your work dealing with "*" in the CSS code.
 I haven't looked into it in detail myself, but * is where undefined is
allowed in AS so it makes sense in principle.  But I'm not sure there is a
need to manually scrub places in AS where undefined is not allowed.
Changing the compiler output might be the better option.  The data you've
provided so far in that regard is helpful though.

>
>> Manually trying to determine whether to use "==" or "===" might be
>> better left to tooling someday, so folks don't have to worry about it
>>and
>> can just get their features to work first.
>
>Folk will run into this issue right away. Most JS devs use == and !== and
>!== instead often evil twins != and ==.
>
>The current behaviour will confuse people as code that works on JS will
>work differently in AS and vice versa.
>
>> I'd personally lean towards warning when folks use JS patterns that can
>>cause trouble.
>
>What patterns in particular are you referring to here? Sonar cube is
>waring about issues in our AS code not JS code.

Are you using a Sonar Cube plugin for ActionScript?  Using a JS review of
AS is likely to be inaccurate, IMO.

>
>> For uninitialized references to instances, maybe
>> leaving it uninitialized and using "== null" is best.
>
>Unlikely as it’s between 2x and 10x as slow and using == null as opposed
>to === null can have unexpected results.

I don't remember seeing your test for this.  Can you post it again (or a
link to the original)?

>> Ints are initialized to zero because the common patterns fail if you
>> don't, not just because of "==" tests.
>
>And I think we have the same issue with Booleans and perhaps Numbers.

Again, think of the allowed patterns when coming from AS, not all possible
JS patterns.
>
>> But there might be other ways to end up with
>> better code than manually scrubbing the source.
>
>Like what? Please provide data an/or examples and/or facts over option
>please.

[1] mentions hidden classes.  If we can make sure our code leverages these
hidden classes, it may turn out that at runtime, there is no difference
between "==" and "===" for ints.

Thanks,
-Alex

[1] https://www.html5rocks.com/en/tutorials/speed/v8/

Reply | Threaded
Open this post in threaded view
|

Re: Private properties are undefined in JS and null in AS

Josh Tynjala
> Again, think of the allowed patterns when coming from AS, not all
possible JS patterns.

I keep seeing you say something like this, Alex. However, Justin is
pointing out perfectly valid AS patterns that are failing in our generated
JS.

- Josh

On Mon, Jun 5, 2017 at 8:37 AM, Alex Harui <[hidden email]> wrote:

>
>
> On 6/4/17, 1:52 AM, "Justin Mclean" <[hidden email]> wrote:
>
> >Hi,
> >
> >> Here is a link [1] to you saying "I’m a strong believer in getting it to
> >> work first, then optimise it, premature optimisation wastes time and
> >>often
> >> makes incorrect assumptions.”
> >
> >That’s exactly what I’m doing. I has something that works and I want to
> >improve the performance.
> >
> >I’d say making something working 5x as fast, with no other costs, is
> >hardly premature optimisation. You’re milage of cause may vary.
>
> I think everyone is supporting your work dealing with "*" in the CSS code.
>  I haven't looked into it in detail myself, but * is where undefined is
> allowed in AS so it makes sense in principle.  But I'm not sure there is a
> need to manually scrub places in AS where undefined is not allowed.
> Changing the compiler output might be the better option.  The data you've
> provided so far in that regard is helpful though.
> >
> >> Manually trying to determine whether to use "==" or "===" might be
> >> better left to tooling someday, so folks don't have to worry about it
> >>and
> >> can just get their features to work first.
> >
> >Folk will run into this issue right away. Most JS devs use == and !== and
> >!== instead often evil twins != and ==.
> >
> >The current behaviour will confuse people as code that works on JS will
> >work differently in AS and vice versa.
> >
> >> I'd personally lean towards warning when folks use JS patterns that can
> >>cause trouble.
> >
> >What patterns in particular are you referring to here? Sonar cube is
> >waring about issues in our AS code not JS code.
>
> Are you using a Sonar Cube plugin for ActionScript?  Using a JS review of
> AS is likely to be inaccurate, IMO.
>
> >
> >> For uninitialized references to instances, maybe
> >> leaving it uninitialized and using "== null" is best.
> >
> >Unlikely as it’s between 2x and 10x as slow and using == null as opposed
> >to === null can have unexpected results.
>
> I don't remember seeing your test for this.  Can you post it again (or a
> link to the original)?
>
> >> Ints are initialized to zero because the common patterns fail if you
> >> don't, not just because of "==" tests.
> >
> >And I think we have the same issue with Booleans and perhaps Numbers.
>
> Again, think of the allowed patterns when coming from AS, not all possible
> JS patterns.
> >
> >> But there might be other ways to end up with
> >> better code than manually scrubbing the source.
> >
> >Like what? Please provide data an/or examples and/or facts over option
> >please.
>
> [1] mentions hidden classes.  If we can make sure our code leverages these
> hidden classes, it may turn out that at runtime, there is no difference
> between "==" and "===" for ints.
>
> Thanks,
> -Alex
>
> [1] https://www.html5rocks.com/en/tutorials/speed/v8/
>
>
Reply | Threaded
Open this post in threaded view
|

Re: Private properties are undefined in JS and null in AS

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

> Are you using a Sonar Cube plugin for ActionScript?  Using a JS review of
> AS is likely to be inaccurate, IMO.

It’s AS see [1]

> it may turn out that at runtime, there is no difference
> between "==" and "===" for ints.

For int the is less of a difference but as discussed it depends if JS knows there are ints on both sides or not. Given that int are defaulting to 0 it’s unlikely to be an issue for AS code involving ints.

Thanks,
Justin

1. https://builds.apache.org/analysis/overview?id=20942