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 <harbs.li...@gmail.com> 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 <harbs.li...@gmail.com> wrote: > >> This discussion fell off the dev list... >> >> Begin forwarded message: >> >>> From: Harbs <harbs.li...@gmail.com> >>> Subject: Re: FlexJS XML string assignment >>> Date: August 6, 2016 at 11:50:29 PM GMT+3 >>> To: Alex Harui <aha...@adobe.com> >>> >>> 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 <aha...@adobe.com> 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 <aha...@adobe.com> 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 <harbs.li...@gmail.com> 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 <harbs.li...@gmail.com> 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 <harbs.li...@gmail.com> 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 <aha...@adobe.com> wrote: >>>>>>>> >>>>>>>>> Pushed it. Hope it works. >>>>>>>>> >>>>>>>>> From: Harbs <harbs.li...@gmail.com> >>>>>>>>> Date: Friday, August 5, 2016 at 12:07 AM >>>>>>>>> To: Alex Harui <aha...@adobe.com> >>>>>>>>> Subject: Re: FlexJS XML string assignment >>>>>>>>> >>>>>>>>> That sounds strange. >>>>>>>>> >>>>>>>>> Thanks for working on this! :-) >>>>>>>>> >>>>>>>>> On Aug 5, 2016, at 9:46 AM, Alex Harui <aha...@adobe.com> 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 <harbs.li...@gmail.com> >>>>>>>>>> Date: Thursday, August 4, 2016 at 2:14 PM >>>>>>>>>> To: Alex Harui <aha...@adobe.com> >>>>>>>>>> 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 <aha...@adobe.com> wrote: >>>>>>>>>> >>>>>>>>>>> I found that it only works in initializers. I'm working on >>>>>>>>>>> expressions now. >>>>>>>>>>> >>>>>>>>>>> -Alex >>>>>>>>>>> >>>>>>>>>>> From: Harbs <harbs.li...@gmail.com> >>>>>>>>>>> Date: Thursday, August 4, 2016 at 1:26 PM >>>>>>>>>>> To: Alex Harui <aha...@adobe.com> >>>>>>>>>>> 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 <aha...@adobe.com> 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" <harbs.li...@gmail.com> 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 <aha...@adobe.com> wrote: >>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> On 8/4/16, 7:22 AM, "Harbs" <harbs.li...@gmail.com> 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 >>>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>> >>>>>>>>> >>>>>>>> >>>>>>> >>>>>> >>>>> >>>> >>> >> >