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 >>>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>> >>>>>>>>> >>>>>>>> >>>>>>> >>>>>> >>>>> >>>> >>> >> >