BTW, I think another change to Language is a good idea:
Currently default function parameters are compiled like this:
public static function getBottomValue(value:Object, values:Object,
reference:Number = NaN):Number
{
return getSideValue(value, values, 2, reference);
}
org.apache.flex.utils.CSSUtils.getBottomValue = function(value, values,
reference) {
reference = typeof reference !== 'undefined' ? reference : NaN;
return org.apache.flex.utils.CSSUtils.getSideValue(value, values, 2,
reference);
};
This line cannot be completely optimized by the Closure compiler:
reference = typeof reference !== 'undefined' ? reference : NaN;
Here’s the best it does:
c='undefined'!==typeof c?c:NaN;
By doing this:
Language.initialize(reference,”Number",NaN);
I think it can be optimized to something like:
cZ(c,fG,NaN);
On Aug 7, 2016, at 11:55 AM, Harbs <[email protected]> wrote:
> To sum up:
>
> There are a number of issues involved here.
>
> What started with a concern about implicit type conversions on XML turned
> into a much broader issue.
>
> In ActionScript, when you assign any object type to typed variable of a
> primitive type (or really any type), it is implicitly converted. Here’s a
> list of the possible type conversions that I could think of:
>
> int: possible values — any integer
> unit: possible values — any positive integer
> Number: possible values — a number or NaN
> Boolean: possible values — true or false
> String: possible values — a string or null
> Object: possible values — an object or null
> “*” (untyped): possible values — undefined, null or any object
>
> Number(obj) and Boolean(obj) would just do the right thing.
>
> obj.toString() does the wrong thing. So does String(obj) — String(null) gives
> you “null” and String(undefined) gives you “undefined”.
>
> As far as int and uint go, I’m not 100% sure what the “right thing” is.
>
> Object casting should probably more-or-less do what Language.as currently
> does and return either the object if possible, or null.
>
> Untyped types should be left alone.
>
> Practically, you VERY rarely want implicit conversions of Objects to strings.
> I think the average client would be doing toString() or some other conversion
> manually. I think XML is an exception to this because E4X blurs the
> distinction between different types and E4X relies pretty heavily on implicit
> conversions.
>
> What I noticed in my code is that by making XML and XMLList classes pretend
> they are strings and numbers, that solves virtually all the implicit
> conversions I had. The biggest exception to that was comparisons between
> XMLLists converted to strings. As it turns out, these comparisons were done
> exclusively in function calls. If function parameters are converted to their
> types, that solves every single case I’ve encountered so far. Logically,
> assuming that function parameters have the correct types make sense that it
> should be more rigid than normal variables.
>
> In a purist sense, it makes sense to ensure type safety, but practically, you
> will not always want it. If you have a tight loop which sets variables many
> thousands of times, you’re not going to want the extra cycles type testing
> your variables. Also, adding code for type checks everywhere will inflate
> code size.
>
> I’d like to see three levels of compiler options:
>
> Level 1 would be no implicit conversions anywhere.
> Level 2 would be conversions on function parameters.
> Level 3 would be conversions everywhere (except untyped variables).
>
> I’m not sure what the default should be, but I think there should be a choice
> between type safety and leaner code.
>
> As far as how to do the conversions, I think it should be a Language function:
> Language.castString(obj) which would test for undefined and null and then do
> a toString() cast otherwise.
>
> (That is, unless “as” currently does the right thing, which I don’t think it
> does).
>
> One thing that might not be clear:
>
> Coercion should only happen on *assignment*. Coercion on comparisons should
> not happen because the conversions happen implicitly in the JS engine if
> required.
>
> On Aug 7, 2016, at 7:39 AM, Harbs <[email protected]> wrote:
>
>> This discussion fell off the dev list...
>>
>> Begin forwarded message:
>>
>>> From: Harbs <[email protected]>
>>> Subject: Re: FlexJS XML string assignment
>>> Date: August 6, 2016 at 11:50:29 PM GMT+3
>>> To: Alex Harui <[email protected]>
>>>
>>> With the exception of XML, I cannot imagine a case where you’d want there
>>> to be an implicit conversion to a string.
>>>
>>> I’m fine with requiring an explicit conversion using toString() or “” + obj
>>> for the client when they want the conversion.
>>>
>>> I think it’s a reasonable trade-off to not add all those toStrings when
>>> they are not necessary. Adding null (and undefined) checks is even worse. I
>>> think a preference should be placed on compact JS code rather than 100%
>>> compatibility with Flash.
>>>
>>> Maybe we should move this discussion to the list.
>>>
>>> On Aug 6, 2016, at 11:35 PM, Alex Harui <[email protected]> wrote:
>>>
>>>> Good point about null. But if we don't call tostring won't there be
>>>> conversion issues when objects are not null? Maybe we need to add null
>>>> check or call a I utils.language method.
>>>>
>>>> Sent from my LG G3, an AT&T 4G LTE smartphone
>>>>
>>>> ------ Original message------
>>>> From: Harbs
>>>> Date: Sat, Aug 6, 2016 1:02 PM
>>>> To: Alex Harui;
>>>> Subject:Re: FlexJS XML string assignment
>>>>
>>>> Because Objects and * can be null and/or undefined (for *).
>>>>
>>>> Assigning null objects and undefined is prefectly valid, but by adding
>>>> toString(), that causes a runtime error. This is exactly what happened to
>>>> me with this:
>>>> this._uri = qNameOrUri.toString();
>>>>
>>>>
>>>> On Aug 6, 2016, at 10:58 PM, Alex Harui <[email protected]> wrote:
>>>>
>>>>> I didn't think the implicit conversion problem is restricted only to xml.
>>>>> Why wouldn't it apply to objects and *?
>>>>>
>>>>> Sent from my LG G3, an AT&T 4G LTE smartphone
>>>>>
>>>>> ------ Original message------
>>>>> From: Harbs
>>>>> Date: Sat, Aug 6, 2016 12:56 PM
>>>>> To: Alex Harui;
>>>>> Subject:Re: FlexJS XML string assignment
>>>>>
>>>>> Another:
>>>>> ns.prefix = attr.split(":")[1].toString();
>>>>>
>>>>> On Aug 6, 2016, at 10:44 PM, Harbs <[email protected]> wrote:
>>>>>
>>>>>> Here’s another good one:
>>>>>> This (in XMLList.plus()):
>>>>>> return this.toString() + rightHand.toString();
>>>>>> becomes:
>>>>>> return this.toString() + rightHand.toString().toString();
>>>>>>
>>>>>> On Aug 6, 2016, at 10:30 PM, Harbs <[email protected]> wrote:
>>>>>>
>>>>>>> There’s lots of extra Number() casts as well:
>>>>>>>
>>>>>>> XML.prototype.attributes = function() {
>>>>>>> var /** @type {number} */ i;
>>>>>>> var /** @type {XMLList} */ list = new XMLList();
>>>>>>> for (i = 0; i < Number(this._attributes.length); i++)
>>>>>>> list.appendChild(this._attributes[i]);
>>>>>>> list.targetObject = this;
>>>>>>> return list;
>>>>>>> };
>>>>>>>
>>>>>>> _attributes is an Array — not XML. There’s no reason to add Number().
>>>>>>>
>>>>>>> On Aug 6, 2016, at 10:22 PM, Harbs <[email protected]> wrote:
>>>>>>>
>>>>>>>> I breaks the XML classes (and I’m not sure what else… ;-)
>>>>>>>>
>>>>>>>> QName = function(qNameOrUri, localNameVal) {
>>>>>>>> qNameOrUri = typeof qNameOrUri !== 'undefined' ? qNameOrUri : null;
>>>>>>>> localNameVal = typeof localNameVal !== 'undefined' ? localNameVal :
>>>>>>>> null;
>>>>>>>> if (org.apache.flex.utils.Language.is(qNameOrUri, QName)) {
>>>>>>>> this._uri = qNameOrUri.uri.toString();
>>>>>>>> this._localName = qNameOrUri.localName.toString();
>>>>>>>> this._prefix = qNameOrUri.prefix.toString();
>>>>>>>> } else if (org.apache.flex.utils.Language.is(qNameOrUri, Namespace))
>>>>>>>> {
>>>>>>>> this._uri = org.apache.flex.utils.Language.as(qNameOrUri,
>>>>>>>> Namespace).uri;
>>>>>>>> this._prefix = org.apache.flex.utils.Language.as(qNameOrUri,
>>>>>>>> Namespace).prefix;
>>>>>>>> if (localNameVal)
>>>>>>>> this._localName = localNameVal.toString().toString();
>>>>>>>> } else if (localNameVal) {
>>>>>>>> this._localName = localNameVal.toString();
>>>>>>>> this._uri = qNameOrUri.toString();
>>>>>>>> } else if (qNameOrUri && qNameOrUri.toString()) {
>>>>>>>> this._localName = qNameOrUri.toString().toString();
>>>>>>>> }
>>>>>>>> };
>>>>>>>>
>>>>>>>> As well as a bunch of extra toString()s in XML.
>>>>>>>>
>>>>>>>> I’m not sure why/how these toString()s are being added. It should only
>>>>>>>> add toString() on something which is typed as XML or XMLList (not
>>>>>>>> Object or *).
>>>>>>>>
>>>>>>>> There’s others as well. In WebStorageProvider.as:
>>>>>>>>
>>>>>>>> newEvent.data = this.result;
>>>>>>>> becomes:
>>>>>>>> newEvent.data = this.result.toString();
>>>>>>>>
>>>>>>>> which is clearly wrong. You don’t want to stringify an ArrayBuffer.
>>>>>>>>
>>>>>>>> I have not done a full audit of the output code. I assume this should
>>>>>>>> be enough for you to address the problem.
>>>>>>>>
>>>>>>>> On Aug 5, 2016, at 5:43 PM, Alex Harui <[email protected]> wrote:
>>>>>>>>
>>>>>>>>> Pushed it. Hope it works.
>>>>>>>>>
>>>>>>>>> From: Harbs <[email protected]>
>>>>>>>>> Date: Friday, August 5, 2016 at 12:07 AM
>>>>>>>>> To: Alex Harui <[email protected]>
>>>>>>>>> Subject: Re: FlexJS XML string assignment
>>>>>>>>>
>>>>>>>>> That sounds strange.
>>>>>>>>>
>>>>>>>>> Thanks for working on this! :-)
>>>>>>>>>
>>>>>>>>> On Aug 5, 2016, at 9:46 AM, Alex Harui <[email protected]> wrote:
>>>>>>>>>
>>>>>>>>>> Hmm. I'll have to finish tomorrow. For some reason the XMLList
>>>>>>>>>> length() function says it is not a number/int.
>>>>>>>>>>
>>>>>>>>>> -Alex
>>>>>>>>>>
>>>>>>>>>> From: Harbs <[email protected]>
>>>>>>>>>> Date: Thursday, August 4, 2016 at 2:14 PM
>>>>>>>>>> To: Alex Harui <[email protected]>
>>>>>>>>>> Subject: Re: FlexJS XML string assignment
>>>>>>>>>>
>>>>>>>>>> OK. Thanks.
>>>>>>>>>>
>>>>>>>>>> I’m done for the day. I’ll take a look in the morning.
>>>>>>>>>>
>>>>>>>>>> Can you tell me which files I would need to copy to the Nightly to
>>>>>>>>>> use a newly compiled Falcon? It looks to me like the only binaries
>>>>>>>>>> which are changed are jsc.jar in compiler-jx/lib and fdb.jar and
>>>>>>>>>> compiler.jar in compiler/lib.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On Aug 5, 2016, at 12:08 AM, Alex Harui <[email protected]> wrote:
>>>>>>>>>>
>>>>>>>>>>> I found that it only works in initializers. I'm working on
>>>>>>>>>>> expressions now.
>>>>>>>>>>>
>>>>>>>>>>> -Alex
>>>>>>>>>>>
>>>>>>>>>>> From: Harbs <[email protected]>
>>>>>>>>>>> Date: Thursday, August 4, 2016 at 1:26 PM
>>>>>>>>>>> To: Alex Harui <[email protected]>
>>>>>>>>>>> Subject: Re: FlexJS XML string assignment
>>>>>>>>>>>
>>>>>>>>>>> Cool.
>>>>>>>>>>>
>>>>>>>>>>> I’ll be happy to test it. I have plenty of cases… ;-)
>>>>>>>>>>>
>>>>>>>>>>> I realized that there’s also Number literal assignments which
>>>>>>>>>>> probably do not work:
>>>>>>>>>>> var tintValue:Number = _rawColorXML.@TintValue;
>>>>>>>>>>>
>>>>>>>>>>> On Aug 4, 2016, at 11:22 PM, Alex Harui <[email protected]> wrote:
>>>>>>>>>>>
>>>>>>>>>>>> I was just testing one set of changes. I'll push them now. It
>>>>>>>>>>>> might not
>>>>>>>>>>>> solve all cases. It might only work for initializing variables.
>>>>>>>>>>>>
>>>>>>>>>>>> On 8/4/16, 1:20 PM, "Harbs" <[email protected]> wrote:
>>>>>>>>>>>>
>>>>>>>>>>>>> Hi Alex,
>>>>>>>>>>>>>
>>>>>>>>>>>>> Do you think this is something you can get to quickly or will it
>>>>>>>>>>>>> take a
>>>>>>>>>>>>> while?
>>>>>>>>>>>>>
>>>>>>>>>>>>> This is something which is holding me up. I can add a whole pile
>>>>>>>>>>>>> of
>>>>>>>>>>>>> toString()s in my code if necessary, but if it’s something that
>>>>>>>>>>>>> might be
>>>>>>>>>>>>> fixed soon, I’ll hold off.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>> Harbs
>>>>>>>>>>>>>
>>>>>>>>>>>>> On Aug 4, 2016, at 5:33 PM, Alex Harui <[email protected]> wrote:
>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> On 8/4/16, 7:22 AM, "Harbs" <[email protected]> wrote:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> I’m not sure how to deal with this case:
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> private var name:String;
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> this.name = someXML.@Name;
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> The above compiles to
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> this.name = someXML.attribute('Name’);
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> In Javascript this.name becomes an XMLList, but in Flash, the
>>>>>>>>>>>>>>> XMLList
>>>>>>>>>>>>>>> is
>>>>>>>>>>>>>>> implicitly converted to a string.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Is it possible to make the compiler smarter and make the
>>>>>>>>>>>>>>> compiled
>>>>>>>>>>>>>>> version
>>>>>>>>>>>>>>> look like this?
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> this.name = someXML.attribute('Name’).toString();
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I will look into it.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> -Alex
>>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
>