You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@royale.apache.org by Harbs <ha...@gmail.com> on 2018/08/06 22:09:10 UTC

XML filters broke

var folderFolders:XMLList = assetXML.folder.(child('key').indexOf(folder.key) == 0);
var folderImages:XMLList = assetXML.image.(child('key').indexOf(folder.key) == 0);

Is now compiled as:

var /** @type {XMLList} */ folderFolders = this.assetXML.child('folder').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
var /** @type {XMLList} */ folderImages = this.assetXML.child('image').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});

“node.folder.key” is not correct. “folder” is a local variable of an un related object type.

I assume this broke with the recent XML filter changes.

Harbs

Re: XML filters broke

Posted by Carlos Rovira <ca...@apache.org>.
Maybe the Storage versions should be renamed to some other name to avoid
confusions...

just my 2ctns

2018-08-09 0:12 GMT+02:00 Harbs <ha...@gmail.com>:

> OK. I think I cherry-picked the files, although there were some conflicts.
> I hope I resolved them correctly.
>
> > On Aug 9, 2018, at 12:45 AM, Alex Harui <ah...@adobe.com.INVALID>
> wrote:
> >
> > The ones in Storage seem to have very different APIs that the flash
> versions and are in a different package.  I'm not sure it is worth worrying
> about right now.
> >
> > AIUI, the ones in Network are intended to mimic the flash versions and
> are what our users are looking for.
> >
> > My 2 cents,
> > -Alex
> >
> > On 8/8/18, 2:43 PM, "Harbs" <ha...@gmail.com> wrote:
> >
> >    It looks like we have duplicate classes in Storage and Network. I
> think we need to pick which package these classes belong in.
> >
> >
> >> On Aug 9, 2018, at 12:38 AM, Alex Harui <ah...@adobe.com.INVALID>
> wrote:
> >>
> >> There's an IDataInput/IDataOutput in the Network.swc in the develop
> branch that would be useful to have in the feature/MXRoyale branch.  I
> don't want to stop to do a full merge right now.
> >>
> >> -Alex
> >>
> >> On 8/8/18, 2:36 PM, "Harbs" <harbs.lists@gmail.com <mailto:
> harbs.lists@gmail.com>> wrote:
> >>
> >>   What’s the issue with IDataInput/IDataOutput? Cherrypicked from where?
> >>
> >>> On Aug 8, 2018, at 11:48 PM, Alex Harui <ah...@adobe.com.INVALID>
> wrote:
> >>>
> >>> Won’t know until we try it.  I'll adjust XMLList as needed.  I have an
> actual test case with Tour De Flex to work with.
> >>>
> >>> If you have time to cherrypick IDataInput/IDataOutput for our users
> that would be helpful.
> >>>
> >>> Thanks,
> >>> -Alex
> >>>
> >>> On 8/8/18, 1:31 PM, "Harbs" <ha...@gmail.com> wrote:
> >>>
> >>>  Are you sure the logic to reassign this will work here?
> >>>
> >>>  I’m willing to rewrite the code in XMLList to use call if you think
> it’ll make things easier in the compiler…
> >>>
> >>>> On Aug 8, 2018, at 11:03 PM, Alex Harui <ah...@adobe.com.INVALID>
> wrote:
> >>>>
> >>>>
> >>>>
> >>>> On 8/8/18, 12:59 AM, "Harbs" <harbs.lists@gmail.com <mailto:
> harbs.lists@gmail.com>> wrote:
> >>>>
> >>>> Does “this” in call/apply even work for a function which is not a
> prototype function? I thought in that case “this” is the global context.
> >>>>
> >>>> From my testing, the 'this' can be re-assigned as we want it.
> >>>>
> >>>> I think 6a is kind of ambiguous. Why do you think there’s a
> difference between the following (other than avoiding ambiguous this
> references)?
> >>>>
> >>>> Because there is already code that distinguishes when 'this' is
> supposed to be used.  So we should use it instead of crafting a whole other
> set of code that has a more difficult problem to solve, like whether an
> expression is relative to a parameter and if so, which parameter?
> >>>>
> >>>> My 2 cents,
> >>>> -Alex
> >>>>
> >>>> function() { return (over40(parseInt(this.age))) }
> >>>> and
> >>>> function(node) { return (over40(parseInt(node.age))) }
> >>>>
> >>>> Although in fact, I think it would need to be:
> >>>>
> >>>> function(node) { return (over40(parseInt(node.child(“age”)))) }
> >>>>
> >>>>> On Aug 8, 2018, at 10:33 AM, Alex Harui <ah...@adobe.com.INVALID>
> wrote:
> >>>>>
> >>>>> EmitterUtils.writeThis seems to be working ok.  I think it would be
> better/correct to use it here.  I'm not sure if node as a parameter creates
> the same scope chain as node being the this pointer.  I think no, I don't
> think parameters are involved in lexical scoping.   IMO, 6a in the spec is
> saying we should make node the 'this' pointer in JS.
> >>>>>
> >>>>> My 2 cents,
> >>>>> -Alex
> >>>>>
> >>>>> On 8/7/18, 10:54 AM, "Harbs" <ha...@gmail.com> wrote:
> >>>>>
> >>>>> I’m not following you. Wouldn’t we need the same logic to figure out
> where to insert “this”? I’m not sure what practical difference there would
> be between “node" and “this”, other than using apply or call. Passing in
> the XML node seems cleaner to me.
> >>>>>
> >>>>>> On Aug 7, 2018, at 6:50 PM, Alex Harui <ah...@adobe.com.INVALID>
> wrote:
> >>>>>>
> >>>>>> Yup.  After thinking about it some more, it occurs to me that we
> took the wrong starting point.  Right now code like:
> >>>>>>
> >>>>>> over40(parseInt(age))
> >>>>>>
> >>>>>> Results in:
> >>>>>>
> >>>>>> function(node) { return (over40(parseInt(age))) }
> >>>>>>
> >>>>>> And then the XML filter calls that function passing itself in as
> the node.
> >>>>>>
> >>>>>> And this discussion has been about trying to figure out where to
> add the "node" parameter.  But now I think that 6a in the spec is really
> saying that the 'this' pointer should be the node.  We should transpile
> that filter expression like any other function body but assume it is a
> function run in the context of the node, like a new method on XML/XMLList,
> or maybe more like an anonymous function.
> >>>>>>
> >>>>>> So if I'm right, then the output should be:
> >>>>>>
> >>>>>> function() { return (over40(parseInt(this.age))) }
> >>>>>>
> >>>>>> This is what the transpiler would have output if you had subclassed
> XML and added this method to it.  And then the code in XML.SWC that applies
> the filter has to use Function.apply/call passing the node as the 'this'
> pointer.
> >>>>>>
> >>>>>> If we do that, then the EmitterUtils.writeE4xFilterNode would go
> away, and JSRoyaleEmitter.emitE4xFilter would temporarily change the
> model.currentClass and maybe a few other things to reference an XML object.
> >>>>>>
> >>>>>> Thoughts?
> >>>>>> -Alex
> >>>>>>
> >>>>>> PS: Regarding adding tests, the filter tests have two variables.
> "var a" sets up the XML, "var b" is the result of the filter.  getVariable
> returns the nodes for "a" then we go get child(1) which is "b" and then
> emit it to see what we get.
> >>>>>>
> >>>>>> On 8/7/18, 3:51 AM, "Harbs" <harbs.lists@gmail.com <mailto:
> harbs.lists@gmail.com>> wrote:
> >>>>>>
> >>>>>> I’m also pretty sure that the following from Mozilla’s page[1] will
> not work correctly:
> >>>>>>
> >>>>>> var people = <people>
> >>>>>> <person>
> >>>>>>   <name>Bob</name>
> >>>>>>   <age>32</age>
> >>>>>> </person>
> >>>>>> <person>
> >>>>>>   <name>Joe</name>
> >>>>>>   <age>46</age>
> >>>>>> </person>
> >>>>>> </people>;
> >>>>>>
> >>>>>> function over40(i) {
> >>>>>>   return i > 40;
> >>>>>> }
> >>>>>>
> >>>>>> alert(people.person.(over40(parseInt(age))).name); // Alerts Joe
> >>>>>>
> >>>>>> https://na01.safelinks.protection.outlook.com/?url=
> https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%
> 2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%
> 7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178de
> cee1%7C0%7C0%7C636693613904214807&amp;sdata=f1j%
> 2BqxKd5WDPLl8d41i2XcLUMxLvNLmuyy%2BFV6GePtc%3D&amp;reserved=0 <
> https://na01.safelinks.protection.outlook.com/?url=
> https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%
> 2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%
> 7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178de
> cee1%7C0%7C0%7C636693613904214807&amp;sdata=f1j%
> 2BqxKd5WDPLl8d41i2XcLUMxLvNLmuyy%2BFV6GePtc%3D&amp;reserved=0> <
> https://na01.safelinks.protection.outlook.com/?url=
> https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%
> 2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%
> 7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178de
> cee1%7C0%7C0%7C636693613904214807&amp;sdata=f1j%
> 2BqxKd5WDPLl8d41i2XcLUMxLvNLmuyy%2BFV6GePtc%3D&amp;reserved=0 <
> https://na01.safelinks.protection.outlook.com/?url=
> https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%
> 2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%
> 7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178de
> cee1%7C0%7C0%7C636693613904214807&amp;sdata=f1j%
> 2BqxKd5WDPLl8d41i2XcLUMxLvNLmuyy%2BFV6GePtc%3D&amp;reserved=0>> <
> https://na01.safelinks.protection.outlook.com/?url=
> https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%
> 2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%
> 7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178de
> cee1%7C0%7C0%7C636693613904214807&amp;sdata=f1j%
> 2BqxKd5WDPLl8d41i2XcLUMxLvNLmuyy%2BFV6GePtc%3D&amp;reserved=0 <
> https://na01.safelinks.protection.outlook.com/?url=
> https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%
> 2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%
> 7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178de
> cee1%7C0%7C0%7C636693613904214807&amp;sdata=f1j%
> 2BqxKd5WDPLl8d41i2XcLUMxLvNLmuyy%2BFV6GePtc%3D&amp;reserved=0> <
> https://na01.safelinks.protection.outlook.com/?url=
> https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%
> 2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%
> 7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178de
> cee1%7C0%7C0%7C636693613904214807&amp;sdata=f1j%
> 2BqxKd5WDPLl8d41i2XcLUMxLvNLmuyy%2BFV6GePtc%3D&amp;reserved=0 <
> https://na01.safelinks.protection.outlook.com/?url=
> https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%
> 2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%
> 7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178de
> cee1%7C0%7C0%7C636693613904214807&amp;sdata=f1j%
> 2BqxKd5WDPLl8d41i2XcLUMxLvNLmuyy%2BFV6GePtc%3D&amp;reserved=0>>> <
> https://na01.safelinks.protection.outlook.com/?url=
> https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%
> 2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%
> 7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178de
> cee1%7C0%7C0%7C636693613904224812&amp;sdata=%2Bgtjz1494OOAafpuAJnfbsRXDLi%
> 2FqwXpEIjzJZQ0AAY%3D&amp;reserved=0 <https://na01.safelinks.
> protection.outlook.com/?url=https%3A%2F%2Fdeveloper.
> mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%
> 2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%
> 7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178de
> cee1%7C0%7C0%7C636693613904224812&amp;sdata=%2Bgtjz1494OOAafpuAJnfbsRXDLi%
> 2FqwXpEIjzJZQ0AAY%3D&amp;reserved=0> <https://na01.safelinks.
> protection.outlook.com/?url=https%3A%2F%2Fdeveloper.
> mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%
> 2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%
> 7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178de
> cee1%7C0%7C0%7C636693613904224812&amp;sdata=%2Bgtjz1494OOAafpuAJnfbsRXDLi%
> 2FqwXpEIjzJZQ0AAY%3D&amp;reserved=0 <https://na01.safelinks.
> protection.outlook.com/?url=https%3A%2F%2Fdeveloper.
> mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%
> 2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%
> 7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178de
> cee1%7C0%7C0%7C636693613904224812&amp;sdata=%2Bgtjz1494OOAafpuAJnfbsRXDLi%
> 2FqwXpEIjzJZQ0AAY%3D&amp;reserved=0>> <https://na01.safelinks.
> protection.outlook.com/?url=https%3A%2F%2Fdeveloper.
> mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%
> 2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%
> 7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178de
> cee1%7C0%7C0%7C636693613904224812&amp;sdata=%2Bgtjz1494OOAafpuAJnfbsRXDLi%
> 2FqwXpEIjzJZQ0AAY%3D&amp;reserved=0 <https://na01.safelinks.
> protection.outlook.com/?url=https%3A%2F%2Fdeveloper.
> mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%
> 2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%
> 7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178de
> cee1%7C0%7C0%7C636693613904224812&amp;sdata=%2Bgtjz1494OOAafpuAJnfbsRXDLi%
> 2FqwXpEIjzJZQ0AAY%3D&amp;reserved=0> <https://na01.safelinks.
> protection.outlook.com/?url=https%3A%2F%2Fdeveloper.
> mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%
> 2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%
> 7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178de
> cee1%7C0%7C0%7C636693613904224812&amp;sdata=%2Bgtjz1494OOAafpuAJnfbsRXDLi%
> 2FqwXpEIjzJZQ0AAY%3D&amp;reserved=0 <https://na01.safelinks.
> protection.outlook.com/?url=https%3A%2F%2Fdeveloper.
> mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%
> 2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%
> 7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178de
> cee1%7C0%7C0%7C636693613904224812&amp;sdata=%2Bgtjz1494OOAafpuAJnfbsRXDLi%
> 2FqwXpEIjzJZQ0AAY%3D&amp;reserved=0>>>>
> >>>>>>
> >>>>>>> On Aug 7, 2018, at 1:41 PM, Harbs <ha...@gmail.com> wrote:
> >>>>>>>
> >>>>>>> OK. I fixed the issue, but there’s a couple of loose ends:
> >>>>>>>
> >>>>>>> 1. I don’t know how to add unit tests for these cases. In the
> current unit tests, I see “getNode” and “getVariable” being used. I don’t
> know the logic in setting up tests.
> >>>>>>> 2. I’m not quite sure what "parentNode.getChild(0)” does. What is
> the parent node and will this cause my second case of e.employee.(1 == @id)
> to fail? Removing the check against firstChild caused the
> testXMLFilterWithAttribute test to fail because it prepended “node.” to
> “length()”.
> >>>>>>>
> >>>>>>> P.S. I finally got debugging from Eclipse working on the compiler,
> so hopefully I’ll have a much easier time fixing compiler issues in the
> future. :-)
> >>>>>>>
> >>>>>>> Thanks,
> >>>>>>> Harbs
> >>>>>>>
> >>>>>>>> On Aug 7, 2018, at 10:51 AM, Harbs <ha...@gmail.com> wrote:
> >>>>>>>>
> >>>>>>>> Well, it looks like I was wrong.
> >>>>>>>>
> >>>>>>>> I just tested the following in Flash, and then both give the same
> results (i.e. return the attribute):
> >>>>>>>>
> >>>>>>>> var emp = e.employee.(@id == 1).@name; // name of employee with
> id 1
> >>>>>>>> var foo = e.employee.(1 == @id).@name; // name of employee with
> id 1
> >>>>>>>>
> >>>>>>>>> On Aug 7, 2018, at 10:27 AM, Harbs <ha...@gmail.com>
> wrote:
> >>>>>>>>>
> >>>>>>>>> Your example does not seem to be right to me.
> >>>>>>>>>
> >>>>>>>>> Here’s the overview of how filters are supposed to work from the
> spec:
> >>>>>>>>>
> >>>>>>>>>> Overview
> >>>>>>>>>> When the left operand evaluates to an XML object, the filtering
> predicate adds the left operand to the front of the scope chain of the
> current execution context, evaluates the Expression with the augmented
> scope chain, converts the result to a Boolean value, then restores the
> scope chain. If the result is true, the filtering predicate returns an
> XMLList containing the left operand. Otherwise it returns an empty XMLList.
> >>>>>>>>>> When the left operand is an XMLList, the filtering predicate is
> applied to each XML object in the XMLList in order using the XML object as
> the left operand and the Expression as the right operand. It concatenates
> the results and returns them as a single XMLList containing all the XML
> properties for which the result was true. For example,
> >>>>>>>>>>
> >>>>>>>>>> var john = e.employee.(name == "John"); // employees with name
> John
> >>>>>>>>>> var twoemployees = e.employee.(@id == 0 || @id == 1); //
> employees with id's 0 & 1
> >>>>>>>>>> var emp = e.employee.(@id == 1).name; // name of employee with
> id 1
> >>>>>>>>>>
> >>>>>>>>>> The effect of the filtering predicate is similar to SQL’s WHERE
> clause or XPath’s filtering predicates.
> >>>>>>>>>> For example, the statement:
> >>>>>>>>>>
> >>>>>>>>>> // get the two employees with ids 0 and 1 using a predicate
> >>>>>>>>>> var twoEmployees = e..employee.(@id == 0 || @id == 1);
> >>>>>>>>>>
> >>>>>>>>>> produces the same result as the following set of statements:
> >>>>>>>>>> // get the two employees with the ids 0 and 1 using a for loop
> >>>>>>>>>> var i = 0;
> >>>>>>>>>> var twoEmployees = new XMLList();
> >>>>>>>>>> for each (var p in e..employee) {
> >>>>>>>>>> with (p) {
> >>>>>>>>>> if (@id == 0 || @id == 1) {
> >>>>>>>>>> twoEmployees[i++] = p;
> >>>>>>>>>> }
> >>>>>>>>>> }
> >>>>>>>>>> }
> >>>>>>>>>
> >>>>>>>>> The question is what is "the front of the scope chain of the
> current execution context”? I’m pretty sure that means the start of
> sub-expressions. I don’t see how that can apply to the right-hand of
> comparison expressions. There is nothing in the spec about figuring out if
> a part of an expression is referring to XML or XMLList.
> >>>>>>>>>
> >>>>>>>>>> On Aug 7, 2018, at 9:45 AM, Alex Harui <ah...@adobe.com.INVALID>
> wrote:
> >>>>>>>>>>
> >>>>>>>>>> I don't get what portion of the spec has to do with whether we
> append "node" to various expressions.  IMO, the changes I made only affect
> 6b.  6a is handled by generating a function with "node" as the parameter
> (because node is list[i] in the spec).  The task in 6b is to correctly
> evaluate any e4x filter expression. I'm not sure what the limits are on
> what you can have in a filter expression, but if you can have just plain
> "@app" anywhere in the filter expression, I don't believe scoping rules
> would know to apply that to the "node" parameter without generating the
> "node" before "@app".
> >>>>>>>>>>
> >>>>>>>>>> There is a chance that the Flex Compiler was using "magic" to
> generate the "node" and really should have reported an error.  I do
> remember being told that the filter function can be "anything".  Even:
> >>>>>>>>>> (var foo:int = @app.length(); foo > @bar.length())
> >>>>>>>>>>
> >>>>>>>>>> If there are actual rules in the spec about evaluating the
> expression, that might apply to how we handle these expressions, otherwise
> I think the right thing is to resolve each expression and if the expression
> does not resolve to anything else, assume that it applies to the node.   I
> know the logic in EmitterUtils.writeE4xFilterNode isn't covering all
> cases.  It is trying to see what the expression resolves to, and returns
> false for known conditions (like a member of a class).  Just make it return
> false for your case (and feel free to add that case to the tests).
> Eventually we'll have enough cases to either call it "good enough" or
> figure out a better way to determine when the expression applies to "node".
> >>>>>>>>>>
> >>>>>>>>>> My 2 cents,
> >>>>>>>>>> -Alex
> >>>>>>>>>>
> >>>>>>>>>> On 8/6/18, 11:20 PM, "Harbs" <ha...@gmail.com> wrote:
> >>>>>>>>>>
> >>>>>>>>>> I just looked at the spec. I think it’s correct to append
> “node” to the first statement of the expression only. The only exception
> seems to be expressions which use boolean expressions (i.e. || or &&) in
> which case each piece of the boolean expression should be considered a
> self-contained expression. So in your example, there are really two filter
> expressions:
> >>>>>>>>>> 1. hasOwnProperty("@app”)
> >>>>>>>>>> 2. @app.length() > 0
> >>>>>>>>>>
> >>>>>>>>>> Both of those should have node appended to the front, but
> nothing else.
> >>>>>>>>>>
> >>>>>>>>>> Here’s the relevant semantics in the spec (the important bit
> being 6a):
> >>>>>>>>>>
> >>>>>>>>>>> 6. For i = 0 to list.[[Length]]-1
> >>>>>>>>>>> a. Add list[i] to the front of the scope chain
> >>>>>>>>>>> b. Let ref be the result of evaluating Expression using the
> augmented scope chain of step 6a
> >>>>>>>>>>> c. Let match = ToBoolean(GetValue(ref))
> >>>>>>>>>>> d. Remove list[i] from the front of the scope chain
> >>>>>>>>>>> e. If (match == true), call the [[Append]] method of r with
> argument list[i]
> >>>>>>>>>>> 7. Return r
> >>>>>>>>>>
> >>>>>>>>>> Makes sense?
> >>>>>>>>>>
> >>>>>>>>>> Harbs
> >>>>>>>>>>
> >>>>>>>>>>> On Aug 7, 2018, at 1:39 AM, Alex Harui
> <ah...@adobe.com.INVALID> wrote:
> >>>>>>>>>>>
> >>>>>>>>>>> In porting Tour De Flex, there were patterns like this
> (explorerTree is XML):
> >>>>>>>>>>>
> >>>>>>>>>>> explorerTree..node.(hasOwnProperty("@app") && @app.length() >
> 0)
> >>>>>>>>>>>
> >>>>>>>>>>> The compiler logic before I made any changes yesterday just
> assumed that the first expression was a reference to the node parameter but
> other expressions were not, but it looks like the expression
> "@app.length()" was allowed in Flex as a reference to the node.  So I think
> the compiler has to determine what expressions evaluate to "nothing" which
> implies they are references to the node, and what did resolve to
> something.  This is all new logic and I don't know how to determine all of
> the test cases up front, so we'll have to keep tuning it as we find
> patterns that don't work as we want them to.
> >>>>>>>>>>>
> >>>>>>>>>>> In your case, if the expression resolves to a
> VariableDefinition, that probably means that isn't a reference to node.
> Not exactly sure, so you should debug into it to see what the node pattern
> is and return false.
> >>>>>>>>>>>
> >>>>>>>>>>> Thanks,
> >>>>>>>>>>> -Alex
> >>>>>>>>>>>
> >>>>>>>>>>> On 8/6/18, 3:28 PM, "Harbs" <ha...@gmail.com> wrote:
> >>>>>>>>>>>
> >>>>>>>>>>> Doesn’t it always need to be a method for it to reference the
> node?
> >>>>>>>>>>>
> >>>>>>>>>>> I.e. child() should be node.child(), but foo.baz would not.
> >>>>>>>>>>>
> >>>>>>>>>>>> On Aug 7, 2018, at 1:12 AM, Alex Harui
> <ah...@adobe.com.INVALID> wrote:
> >>>>>>>>>>>>
> >>>>>>>>>>>> Yep, we need more intelligent understanding of when a
> reference is to the node or not.
> >>>>>>>>>>>>
> >>>>>>>>>>>> Debug into EmitterUtils.writeE4xFilterNode and figure out
> the node pattern you need.
> >>>>>>>>>>>>
> >>>>>>>>>>>> -Alex
> >>>>>>>>>>>>
> >>>>>>>>>>>> On 8/6/18, 3:09 PM, "Harbs" <ha...@gmail.com> wrote:
> >>>>>>>>>>>>
> >>>>>>>>>>>> var folderFolders:XMLList = assetXML.folder.(child('key').indexOf(folder.key)
> == 0);
> >>>>>>>>>>>> var folderImages:XMLList = assetXML.image.(child('key').indexOf(folder.key)
> == 0);
> >>>>>>>>>>>>
> >>>>>>>>>>>> Is now compiled as:
> >>>>>>>>>>>>
> >>>>>>>>>>>> var /** @type {XMLList} */ folderFolders =
> this.assetXML.child('folder').filter(function(node){return
> (node.child('key').indexOf(node.folder.key) == 0)});
> >>>>>>>>>>>> var /** @type {XMLList} */ folderImages =
> this.assetXML.child('image').filter(function(node){return
> (node.child('key').indexOf(node.folder.key) == 0)});
> >>>>>>>>>>>>
> >>>>>>>>>>>> “node.folder.key” is not correct. “folder” is a local
> variable of an un related object type.
> >>>>>>>>>>>>
> >>>>>>>>>>>> I assume this broke with the recent XML filter changes.
> >>>>>>>>>>>>
> >>>>>>>>>>>> Harbs
> >
> >
> >
>
>


-- 
Carlos Rovira
http://about.me/carlosrovira

Re: XML filters broke

Posted by Harbs <ha...@gmail.com>.
OK. I think I cherry-picked the files, although there were some conflicts. I hope I resolved them correctly.

> On Aug 9, 2018, at 12:45 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
> 
> The ones in Storage seem to have very different APIs that the flash versions and are in a different package.  I'm not sure it is worth worrying about right now.
> 
> AIUI, the ones in Network are intended to mimic the flash versions and are what our users are looking for.
> 
> My 2 cents,
> -Alex
> 
> On 8/8/18, 2:43 PM, "Harbs" <ha...@gmail.com> wrote:
> 
>    It looks like we have duplicate classes in Storage and Network. I think we need to pick which package these classes belong in.
> 
> 
>> On Aug 9, 2018, at 12:38 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>> 
>> There's an IDataInput/IDataOutput in the Network.swc in the develop branch that would be useful to have in the feature/MXRoyale branch.  I don't want to stop to do a full merge right now.
>> 
>> -Alex
>> 
>> On 8/8/18, 2:36 PM, "Harbs" <harbs.lists@gmail.com <ma...@gmail.com>> wrote:
>> 
>>   What’s the issue with IDataInput/IDataOutput? Cherrypicked from where?
>> 
>>> On Aug 8, 2018, at 11:48 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>> 
>>> Won’t know until we try it.  I'll adjust XMLList as needed.  I have an actual test case with Tour De Flex to work with.
>>> 
>>> If you have time to cherrypick IDataInput/IDataOutput for our users that would be helpful.
>>> 
>>> Thanks,
>>> -Alex
>>> 
>>> On 8/8/18, 1:31 PM, "Harbs" <ha...@gmail.com> wrote:
>>> 
>>>  Are you sure the logic to reassign this will work here?
>>> 
>>>  I’m willing to rewrite the code in XMLList to use call if you think it’ll make things easier in the compiler…
>>> 
>>>> On Aug 8, 2018, at 11:03 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>> 
>>>> 
>>>> 
>>>> On 8/8/18, 12:59 AM, "Harbs" <harbs.lists@gmail.com <ma...@gmail.com>> wrote:
>>>> 
>>>> Does “this” in call/apply even work for a function which is not a prototype function? I thought in that case “this” is the global context.
>>>> 
>>>> From my testing, the 'this' can be re-assigned as we want it.
>>>> 
>>>> I think 6a is kind of ambiguous. Why do you think there’s a difference between the following (other than avoiding ambiguous this references)?
>>>> 
>>>> Because there is already code that distinguishes when 'this' is supposed to be used.  So we should use it instead of crafting a whole other set of code that has a more difficult problem to solve, like whether an expression is relative to a parameter and if so, which parameter?
>>>> 
>>>> My 2 cents,
>>>> -Alex
>>>> 
>>>> function() { return (over40(parseInt(this.age))) }
>>>> and 
>>>> function(node) { return (over40(parseInt(node.age))) }
>>>> 
>>>> Although in fact, I think it would need to be:
>>>> 
>>>> function(node) { return (over40(parseInt(node.child(“age”)))) }
>>>> 
>>>>> On Aug 8, 2018, at 10:33 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>>> 
>>>>> EmitterUtils.writeThis seems to be working ok.  I think it would be better/correct to use it here.  I'm not sure if node as a parameter creates the same scope chain as node being the this pointer.  I think no, I don't think parameters are involved in lexical scoping.   IMO, 6a in the spec is saying we should make node the 'this' pointer in JS.
>>>>> 
>>>>> My 2 cents,
>>>>> -Alex
>>>>> 
>>>>> On 8/7/18, 10:54 AM, "Harbs" <ha...@gmail.com> wrote:
>>>>> 
>>>>> I’m not following you. Wouldn’t we need the same logic to figure out where to insert “this”? I’m not sure what practical difference there would be between “node" and “this”, other than using apply or call. Passing in the XML node seems cleaner to me.
>>>>> 
>>>>>> On Aug 7, 2018, at 6:50 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>>>> 
>>>>>> Yup.  After thinking about it some more, it occurs to me that we took the wrong starting point.  Right now code like:
>>>>>> 
>>>>>> over40(parseInt(age))
>>>>>> 
>>>>>> Results in:
>>>>>> 
>>>>>> function(node) { return (over40(parseInt(age))) }
>>>>>> 
>>>>>> And then the XML filter calls that function passing itself in as the node.
>>>>>> 
>>>>>> And this discussion has been about trying to figure out where to add the "node" parameter.  But now I think that 6a in the spec is really saying that the 'this' pointer should be the node.  We should transpile that filter expression like any other function body but assume it is a function run in the context of the node, like a new method on XML/XMLList, or maybe more like an anonymous function.
>>>>>> 
>>>>>> So if I'm right, then the output should be:
>>>>>> 
>>>>>> function() { return (over40(parseInt(this.age))) }
>>>>>> 
>>>>>> This is what the transpiler would have output if you had subclassed XML and added this method to it.  And then the code in XML.SWC that applies the filter has to use Function.apply/call passing the node as the 'this' pointer.
>>>>>> 
>>>>>> If we do that, then the EmitterUtils.writeE4xFilterNode would go away, and JSRoyaleEmitter.emitE4xFilter would temporarily change the model.currentClass and maybe a few other things to reference an XML object.
>>>>>> 
>>>>>> Thoughts?
>>>>>> -Alex
>>>>>> 
>>>>>> PS: Regarding adding tests, the filter tests have two variables.  "var a" sets up the XML, "var b" is the result of the filter.  getVariable returns the nodes for "a" then we go get child(1) which is "b" and then emit it to see what we get.
>>>>>> 
>>>>>> On 8/7/18, 3:51 AM, "Harbs" <harbs.lists@gmail.com <ma...@gmail.com>> wrote:
>>>>>> 
>>>>>> I’m also pretty sure that the following from Mozilla’s page[1] will not work correctly:
>>>>>> 
>>>>>> var people = <people>
>>>>>> <person>
>>>>>>   <name>Bob</name>
>>>>>>   <age>32</age>
>>>>>> </person>
>>>>>> <person>
>>>>>>   <name>Joe</name>
>>>>>>   <age>46</age>
>>>>>> </person>
>>>>>> </people>;
>>>>>> 
>>>>>> function over40(i) {
>>>>>>   return i > 40;
>>>>>> }
>>>>>> 
>>>>>> alert(people.person.(over40(parseInt(age))).name); // Alerts Joe
>>>>>> 
>>>>>> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904214807&amp;sdata=f1j%2BqxKd5WDPLl8d41i2XcLUMxLvNLmuyy%2BFV6GePtc%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904214807&amp;sdata=f1j%2BqxKd5WDPLl8d41i2XcLUMxLvNLmuyy%2BFV6GePtc%3D&amp;reserved=0> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904214807&amp;sdata=f1j%2BqxKd5WDPLl8d41i2XcLUMxLvNLmuyy%2BFV6GePtc%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904214807&amp;sdata=f1j%2BqxKd5WDPLl8d41i2XcLUMxLvNLmuyy%2BFV6GePtc%3D&amp;reserved=0>> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904214807&amp;sdata=f1j%2BqxKd5WDPLl8d41i2XcLUMxLvNLmuyy%2BFV6GePtc%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904214807&amp;sdata=f1j%2BqxKd5WDPLl8d41i2XcLUMxLvNLmuyy%2BFV6GePtc%3D&amp;reserved=0> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904214807&amp;sdata=f1j%2BqxKd5WDPLl8d41i2XcLUMxLvNLmuyy%2BFV6GePtc%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904214807&amp;sdata=f1j%2BqxKd5WDPLl8d41i2XcLUMxLvNLmuyy%2BFV6GePtc%3D&amp;reserved=0>>> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904224812&amp;sdata=%2Bgtjz1494OOAafpuAJnfbsRXDLi%2FqwXpEIjzJZQ0AAY%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904224812&amp;sdata=%2Bgtjz1494OOAafpuAJnfbsRXDLi%2FqwXpEIjzJZQ0AAY%3D&amp;reserved=0> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904224812&amp;sdata=%2Bgtjz1494OOAafpuAJnfbsRXDLi%2FqwXpEIjzJZQ0AAY%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904224812&amp;sdata=%2Bgtjz1494OOAafpuAJnfbsRXDLi%2FqwXpEIjzJZQ0AAY%3D&amp;reserved=0>> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904224812&amp;sdata=%2Bgtjz1494OOAafpuAJnfbsRXDLi%2FqwXpEIjzJZQ0AAY%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904224812&amp;sdata=%2Bgtjz1494OOAafpuAJnfbsRXDLi%2FqwXpEIjzJZQ0AAY%3D&amp;reserved=0> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904224812&amp;sdata=%2Bgtjz1494OOAafpuAJnfbsRXDLi%2FqwXpEIjzJZQ0AAY%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904224812&amp;sdata=%2Bgtjz1494OOAafpuAJnfbsRXDLi%2FqwXpEIjzJZQ0AAY%3D&amp;reserved=0>>>>
>>>>>> 
>>>>>>> On Aug 7, 2018, at 1:41 PM, Harbs <ha...@gmail.com> wrote:
>>>>>>> 
>>>>>>> OK. I fixed the issue, but there’s a couple of loose ends:
>>>>>>> 
>>>>>>> 1. I don’t know how to add unit tests for these cases. In the current unit tests, I see “getNode” and “getVariable” being used. I don’t know the logic in setting up tests.
>>>>>>> 2. I’m not quite sure what "parentNode.getChild(0)” does. What is the parent node and will this cause my second case of e.employee.(1 == @id) to fail? Removing the check against firstChild caused the testXMLFilterWithAttribute test to fail because it prepended “node.” to “length()”.
>>>>>>> 
>>>>>>> P.S. I finally got debugging from Eclipse working on the compiler, so hopefully I’ll have a much easier time fixing compiler issues in the future. :-)
>>>>>>> 
>>>>>>> Thanks,
>>>>>>> Harbs
>>>>>>> 
>>>>>>>> On Aug 7, 2018, at 10:51 AM, Harbs <ha...@gmail.com> wrote:
>>>>>>>> 
>>>>>>>> Well, it looks like I was wrong.
>>>>>>>> 
>>>>>>>> I just tested the following in Flash, and then both give the same results (i.e. return the attribute):
>>>>>>>> 
>>>>>>>> var emp = e.employee.(@id == 1).@name; // name of employee with id 1
>>>>>>>> var foo = e.employee.(1 == @id).@name; // name of employee with id 1
>>>>>>>> 
>>>>>>>>> On Aug 7, 2018, at 10:27 AM, Harbs <ha...@gmail.com> wrote:
>>>>>>>>> 
>>>>>>>>> Your example does not seem to be right to me.
>>>>>>>>> 
>>>>>>>>> Here’s the overview of how filters are supposed to work from the spec:
>>>>>>>>> 
>>>>>>>>>> Overview
>>>>>>>>>> When the left operand evaluates to an XML object, the filtering predicate adds the left operand to the front of the scope chain of the current execution context, evaluates the Expression with the augmented scope chain, converts the result to a Boolean value, then restores the scope chain. If the result is true, the filtering predicate returns an XMLList containing the left operand. Otherwise it returns an empty XMLList.
>>>>>>>>>> When the left operand is an XMLList, the filtering predicate is applied to each XML object in the XMLList in order using the XML object as the left operand and the Expression as the right operand. It concatenates the results and returns them as a single XMLList containing all the XML properties for which the result was true. For example,
>>>>>>>>>> 
>>>>>>>>>> var john = e.employee.(name == "John"); // employees with name John
>>>>>>>>>> var twoemployees = e.employee.(@id == 0 || @id == 1); // employees with id's 0 & 1
>>>>>>>>>> var emp = e.employee.(@id == 1).name; // name of employee with id 1
>>>>>>>>>> 
>>>>>>>>>> The effect of the filtering predicate is similar to SQL’s WHERE clause or XPath’s filtering predicates.
>>>>>>>>>> For example, the statement:
>>>>>>>>>> 
>>>>>>>>>> // get the two employees with ids 0 and 1 using a predicate
>>>>>>>>>> var twoEmployees = e..employee.(@id == 0 || @id == 1);
>>>>>>>>>> 
>>>>>>>>>> produces the same result as the following set of statements:
>>>>>>>>>> // get the two employees with the ids 0 and 1 using a for loop
>>>>>>>>>> var i = 0;
>>>>>>>>>> var twoEmployees = new XMLList();
>>>>>>>>>> for each (var p in e..employee) {
>>>>>>>>>> with (p) {
>>>>>>>>>> if (@id == 0 || @id == 1) {
>>>>>>>>>> twoEmployees[i++] = p;
>>>>>>>>>> }
>>>>>>>>>> }
>>>>>>>>>> }
>>>>>>>>> 
>>>>>>>>> The question is what is "the front of the scope chain of the current execution context”? I’m pretty sure that means the start of sub-expressions. I don’t see how that can apply to the right-hand of comparison expressions. There is nothing in the spec about figuring out if a part of an expression is referring to XML or XMLList.
>>>>>>>>> 
>>>>>>>>>> On Aug 7, 2018, at 9:45 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>>>>>>>> 
>>>>>>>>>> I don't get what portion of the spec has to do with whether we append "node" to various expressions.  IMO, the changes I made only affect 6b.  6a is handled by generating a function with "node" as the parameter (because node is list[i] in the spec).  The task in 6b is to correctly evaluate any e4x filter expression. I'm not sure what the limits are on what you can have in a filter expression, but if you can have just plain "@app" anywhere in the filter expression, I don't believe scoping rules would know to apply that to the "node" parameter without generating the "node" before "@app".
>>>>>>>>>> 
>>>>>>>>>> There is a chance that the Flex Compiler was using "magic" to generate the "node" and really should have reported an error.  I do remember being told that the filter function can be "anything".  Even:
>>>>>>>>>> (var foo:int = @app.length(); foo > @bar.length())  
>>>>>>>>>> 
>>>>>>>>>> If there are actual rules in the spec about evaluating the expression, that might apply to how we handle these expressions, otherwise I think the right thing is to resolve each expression and if the expression does not resolve to anything else, assume that it applies to the node.   I know the logic in EmitterUtils.writeE4xFilterNode isn't covering all cases.  It is trying to see what the expression resolves to, and returns false for known conditions (like a member of a class).  Just make it return false for your case (and feel free to add that case to the tests).  Eventually we'll have enough cases to either call it "good enough" or figure out a better way to determine when the expression applies to "node".
>>>>>>>>>> 
>>>>>>>>>> My 2 cents,
>>>>>>>>>> -Alex
>>>>>>>>>> 
>>>>>>>>>> On 8/6/18, 11:20 PM, "Harbs" <ha...@gmail.com> wrote:
>>>>>>>>>> 
>>>>>>>>>> I just looked at the spec. I think it’s correct to append “node” to the first statement of the expression only. The only exception seems to be expressions which use boolean expressions (i.e. || or &&) in which case each piece of the boolean expression should be considered a self-contained expression. So in your example, there are really two filter expressions:
>>>>>>>>>> 1. hasOwnProperty("@app”)
>>>>>>>>>> 2. @app.length() > 0
>>>>>>>>>> 
>>>>>>>>>> Both of those should have node appended to the front, but nothing else.
>>>>>>>>>> 
>>>>>>>>>> Here’s the relevant semantics in the spec (the important bit being 6a):
>>>>>>>>>> 
>>>>>>>>>>> 6. For i = 0 to list.[[Length]]-1
>>>>>>>>>>> a. Add list[i] to the front of the scope chain
>>>>>>>>>>> b. Let ref be the result of evaluating Expression using the augmented scope chain of step 6a
>>>>>>>>>>> c. Let match = ToBoolean(GetValue(ref))
>>>>>>>>>>> d. Remove list[i] from the front of the scope chain
>>>>>>>>>>> e. If (match == true), call the [[Append]] method of r with argument list[i]
>>>>>>>>>>> 7. Return r
>>>>>>>>>> 
>>>>>>>>>> Makes sense?
>>>>>>>>>> 
>>>>>>>>>> Harbs
>>>>>>>>>> 
>>>>>>>>>>> On Aug 7, 2018, at 1:39 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>>>>>>>>> 
>>>>>>>>>>> In porting Tour De Flex, there were patterns like this (explorerTree is XML):
>>>>>>>>>>> 
>>>>>>>>>>> explorerTree..node.(hasOwnProperty("@app") && @app.length() > 0)
>>>>>>>>>>> 
>>>>>>>>>>> The compiler logic before I made any changes yesterday just assumed that the first expression was a reference to the node parameter but other expressions were not, but it looks like the expression "@app.length()" was allowed in Flex as a reference to the node.  So I think the compiler has to determine what expressions evaluate to "nothing" which implies they are references to the node, and what did resolve to something.  This is all new logic and I don't know how to determine all of the test cases up front, so we'll have to keep tuning it as we find patterns that don't work as we want them to.
>>>>>>>>>>> 
>>>>>>>>>>> In your case, if the expression resolves to a VariableDefinition, that probably means that isn't a reference to node.  Not exactly sure, so you should debug into it to see what the node pattern is and return false.
>>>>>>>>>>> 
>>>>>>>>>>> Thanks,
>>>>>>>>>>> -Alex
>>>>>>>>>>> 
>>>>>>>>>>> On 8/6/18, 3:28 PM, "Harbs" <ha...@gmail.com> wrote:
>>>>>>>>>>> 
>>>>>>>>>>> Doesn’t it always need to be a method for it to reference the node?
>>>>>>>>>>> 
>>>>>>>>>>> I.e. child() should be node.child(), but foo.baz would not.
>>>>>>>>>>> 
>>>>>>>>>>>> On Aug 7, 2018, at 1:12 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>>>>>>>>>> 
>>>>>>>>>>>> Yep, we need more intelligent understanding of when a reference is to the node or not.
>>>>>>>>>>>> 
>>>>>>>>>>>> Debug into EmitterUtils.writeE4xFilterNode and figure out the node pattern you need.
>>>>>>>>>>>> 
>>>>>>>>>>>> -Alex
>>>>>>>>>>>> 
>>>>>>>>>>>> On 8/6/18, 3:09 PM, "Harbs" <ha...@gmail.com> wrote:
>>>>>>>>>>>> 
>>>>>>>>>>>> var folderFolders:XMLList = assetXML.folder.(child('key').indexOf(folder.key) == 0);
>>>>>>>>>>>> var folderImages:XMLList = assetXML.image.(child('key').indexOf(folder.key) == 0);
>>>>>>>>>>>> 
>>>>>>>>>>>> Is now compiled as:
>>>>>>>>>>>> 
>>>>>>>>>>>> var /** @type {XMLList} */ folderFolders = this.assetXML.child('folder').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
>>>>>>>>>>>> var /** @type {XMLList} */ folderImages = this.assetXML.child('image').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
>>>>>>>>>>>> 
>>>>>>>>>>>> “node.folder.key” is not correct. “folder” is a local variable of an un related object type.
>>>>>>>>>>>> 
>>>>>>>>>>>> I assume this broke with the recent XML filter changes.
>>>>>>>>>>>> 
>>>>>>>>>>>> Harbs
> 
> 
> 


Re: XML filters broke

Posted by Alex Harui <ah...@adobe.com.INVALID>.
The ones in Storage seem to have very different APIs that the flash versions and are in a different package.  I'm not sure it is worth worrying about right now.

AIUI, the ones in Network are intended to mimic the flash versions and are what our users are looking for.

My 2 cents,
-Alex

On 8/8/18, 2:43 PM, "Harbs" <ha...@gmail.com> wrote:

    It looks like we have duplicate classes in Storage and Network. I think we need to pick which package these classes belong in.
    
    
    > On Aug 9, 2018, at 12:38 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    > 
    > There's an IDataInput/IDataOutput in the Network.swc in the develop branch that would be useful to have in the feature/MXRoyale branch.  I don't want to stop to do a full merge right now.
    > 
    > -Alex
    > 
    > On 8/8/18, 2:36 PM, "Harbs" <harbs.lists@gmail.com <ma...@gmail.com>> wrote:
    > 
    >    What’s the issue with IDataInput/IDataOutput? Cherrypicked from where?
    > 
    >> On Aug 8, 2018, at 11:48 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >> 
    >> Won’t know until we try it.  I'll adjust XMLList as needed.  I have an actual test case with Tour De Flex to work with.
    >> 
    >> If you have time to cherrypick IDataInput/IDataOutput for our users that would be helpful.
    >> 
    >> Thanks,
    >> -Alex
    >> 
    >> On 8/8/18, 1:31 PM, "Harbs" <ha...@gmail.com> wrote:
    >> 
    >>   Are you sure the logic to reassign this will work here?
    >> 
    >>   I’m willing to rewrite the code in XMLList to use call if you think it’ll make things easier in the compiler…
    >> 
    >>> On Aug 8, 2018, at 11:03 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >>> 
    >>> 
    >>> 
    >>> On 8/8/18, 12:59 AM, "Harbs" <harbs.lists@gmail.com <ma...@gmail.com>> wrote:
    >>> 
    >>>  Does “this” in call/apply even work for a function which is not a prototype function? I thought in that case “this” is the global context.
    >>> 
    >>> From my testing, the 'this' can be re-assigned as we want it.
    >>> 
    >>>  I think 6a is kind of ambiguous. Why do you think there’s a difference between the following (other than avoiding ambiguous this references)?
    >>> 
    >>> Because there is already code that distinguishes when 'this' is supposed to be used.  So we should use it instead of crafting a whole other set of code that has a more difficult problem to solve, like whether an expression is relative to a parameter and if so, which parameter?
    >>> 
    >>> My 2 cents,
    >>> -Alex
    >>> 
    >>>  function() { return (over40(parseInt(this.age))) }
    >>>  and 
    >>>  function(node) { return (over40(parseInt(node.age))) }
    >>> 
    >>>  Although in fact, I think it would need to be:
    >>> 
    >>>  function(node) { return (over40(parseInt(node.child(“age”)))) }
    >>> 
    >>>> On Aug 8, 2018, at 10:33 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >>>> 
    >>>> EmitterUtils.writeThis seems to be working ok.  I think it would be better/correct to use it here.  I'm not sure if node as a parameter creates the same scope chain as node being the this pointer.  I think no, I don't think parameters are involved in lexical scoping.   IMO, 6a in the spec is saying we should make node the 'this' pointer in JS.
    >>>> 
    >>>> My 2 cents,
    >>>> -Alex
    >>>> 
    >>>> On 8/7/18, 10:54 AM, "Harbs" <ha...@gmail.com> wrote:
    >>>> 
    >>>> I’m not following you. Wouldn’t we need the same logic to figure out where to insert “this”? I’m not sure what practical difference there would be between “node" and “this”, other than using apply or call. Passing in the XML node seems cleaner to me.
    >>>> 
    >>>>> On Aug 7, 2018, at 6:50 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >>>>> 
    >>>>> Yup.  After thinking about it some more, it occurs to me that we took the wrong starting point.  Right now code like:
    >>>>> 
    >>>>> over40(parseInt(age))
    >>>>> 
    >>>>> Results in:
    >>>>> 
    >>>>> function(node) { return (over40(parseInt(age))) }
    >>>>> 
    >>>>> And then the XML filter calls that function passing itself in as the node.
    >>>>> 
    >>>>> And this discussion has been about trying to figure out where to add the "node" parameter.  But now I think that 6a in the spec is really saying that the 'this' pointer should be the node.  We should transpile that filter expression like any other function body but assume it is a function run in the context of the node, like a new method on XML/XMLList, or maybe more like an anonymous function.
    >>>>> 
    >>>>> So if I'm right, then the output should be:
    >>>>> 
    >>>>> function() { return (over40(parseInt(this.age))) }
    >>>>> 
    >>>>> This is what the transpiler would have output if you had subclassed XML and added this method to it.  And then the code in XML.SWC that applies the filter has to use Function.apply/call passing the node as the 'this' pointer.
    >>>>> 
    >>>>> If we do that, then the EmitterUtils.writeE4xFilterNode would go away, and JSRoyaleEmitter.emitE4xFilter would temporarily change the model.currentClass and maybe a few other things to reference an XML object.
    >>>>> 
    >>>>> Thoughts?
    >>>>> -Alex
    >>>>> 
    >>>>> PS: Regarding adding tests, the filter tests have two variables.  "var a" sets up the XML, "var b" is the result of the filter.  getVariable returns the nodes for "a" then we go get child(1) which is "b" and then emit it to see what we get.
    >>>>> 
    >>>>> On 8/7/18, 3:51 AM, "Harbs" <harbs.lists@gmail.com <ma...@gmail.com>> wrote:
    >>>>> 
    >>>>> I’m also pretty sure that the following from Mozilla’s page[1] will not work correctly:
    >>>>> 
    >>>>> var people = <people>
    >>>>>  <person>
    >>>>>    <name>Bob</name>
    >>>>>    <age>32</age>
    >>>>>  </person>
    >>>>>  <person>
    >>>>>    <name>Joe</name>
    >>>>>    <age>46</age>
    >>>>>  </person>
    >>>>> </people>;
    >>>>> 
    >>>>> function over40(i) {
    >>>>>    return i > 40;
    >>>>> }
    >>>>> 
    >>>>> alert(people.person.(over40(parseInt(age))).name); // Alerts Joe
    >>>>> 
    >>>>> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904214807&amp;sdata=f1j%2BqxKd5WDPLl8d41i2XcLUMxLvNLmuyy%2BFV6GePtc%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904214807&amp;sdata=f1j%2BqxKd5WDPLl8d41i2XcLUMxLvNLmuyy%2BFV6GePtc%3D&amp;reserved=0> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904214807&amp;sdata=f1j%2BqxKd5WDPLl8d41i2XcLUMxLvNLmuyy%2BFV6GePtc%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904214807&amp;sdata=f1j%2BqxKd5WDPLl8d41i2XcLUMxLvNLmuyy%2BFV6GePtc%3D&amp;reserved=0>> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904214807&amp;sdata=f1j%2BqxKd5WDPLl8d41i2XcLUMxLvNLmuyy%2BFV6GePtc%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904214807&amp;sdata=f1j%2BqxKd5WDPLl8d41i2XcLUMxLvNLmuyy%2BFV6GePtc%3D&amp;reserved=0> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904214807&amp;sdata=f1j%2BqxKd5WDPLl8d41i2XcLUMxLvNLmuyy%2BFV6GePtc%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904214807&amp;sdata=f1j%2BqxKd5WDPLl8d41i2XcLUMxLvNLmuyy%2BFV6GePtc%3D&amp;reserved=0>>> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904224812&amp;sdata=%2Bgtjz1494OOAafpuAJnfbsRXDLi%2FqwXpEIjzJZQ0AAY%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904224812&amp;sdata=%2Bgtjz1494OOAafpuAJnfbsRXDLi%2FqwXpEIjzJZQ0AAY%3D&amp;reserved=0> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904224812&amp;sdata=%2Bgtjz1494OOAafpuAJnfbsRXDLi%2FqwXpEIjzJZQ0AAY%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904224812&amp;sdata=%2Bgtjz1494OOAafpuAJnfbsRXDLi%2FqwXpEIjzJZQ0AAY%3D&amp;reserved=0>> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904224812&amp;sdata=%2Bgtjz1494OOAafpuAJnfbsRXDLi%2FqwXpEIjzJZQ0AAY%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904224812&amp;sdata=%2Bgtjz1494OOAafpuAJnfbsRXDLi%2FqwXpEIjzJZQ0AAY%3D&amp;reserved=0> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904224812&amp;sdata=%2Bgtjz1494OOAafpuAJnfbsRXDLi%2FqwXpEIjzJZQ0AAY%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cba4001f9a9d4406f28c708d5fd77ee9b%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693613904224812&amp;sdata=%2Bgtjz1494OOAafpuAJnfbsRXDLi%2FqwXpEIjzJZQ0AAY%3D&amp;reserved=0>>>>
    >>>>> 
    >>>>>> On Aug 7, 2018, at 1:41 PM, Harbs <ha...@gmail.com> wrote:
    >>>>>> 
    >>>>>> OK. I fixed the issue, but there’s a couple of loose ends:
    >>>>>> 
    >>>>>> 1. I don’t know how to add unit tests for these cases. In the current unit tests, I see “getNode” and “getVariable” being used. I don’t know the logic in setting up tests.
    >>>>>> 2. I’m not quite sure what "parentNode.getChild(0)” does. What is the parent node and will this cause my second case of e.employee.(1 == @id) to fail? Removing the check against firstChild caused the testXMLFilterWithAttribute test to fail because it prepended “node.” to “length()”.
    >>>>>> 
    >>>>>> P.S. I finally got debugging from Eclipse working on the compiler, so hopefully I’ll have a much easier time fixing compiler issues in the future. :-)
    >>>>>> 
    >>>>>> Thanks,
    >>>>>> Harbs
    >>>>>> 
    >>>>>>> On Aug 7, 2018, at 10:51 AM, Harbs <ha...@gmail.com> wrote:
    >>>>>>> 
    >>>>>>> Well, it looks like I was wrong.
    >>>>>>> 
    >>>>>>> I just tested the following in Flash, and then both give the same results (i.e. return the attribute):
    >>>>>>> 
    >>>>>>> var emp = e.employee.(@id == 1).@name; // name of employee with id 1
    >>>>>>> var foo = e.employee.(1 == @id).@name; // name of employee with id 1
    >>>>>>> 
    >>>>>>>> On Aug 7, 2018, at 10:27 AM, Harbs <ha...@gmail.com> wrote:
    >>>>>>>> 
    >>>>>>>> Your example does not seem to be right to me.
    >>>>>>>> 
    >>>>>>>> Here’s the overview of how filters are supposed to work from the spec:
    >>>>>>>> 
    >>>>>>>>> Overview
    >>>>>>>>> When the left operand evaluates to an XML object, the filtering predicate adds the left operand to the front of the scope chain of the current execution context, evaluates the Expression with the augmented scope chain, converts the result to a Boolean value, then restores the scope chain. If the result is true, the filtering predicate returns an XMLList containing the left operand. Otherwise it returns an empty XMLList.
    >>>>>>>>> When the left operand is an XMLList, the filtering predicate is applied to each XML object in the XMLList in order using the XML object as the left operand and the Expression as the right operand. It concatenates the results and returns them as a single XMLList containing all the XML properties for which the result was true. For example,
    >>>>>>>>> 
    >>>>>>>>> var john = e.employee.(name == "John"); // employees with name John
    >>>>>>>>> var twoemployees = e.employee.(@id == 0 || @id == 1); // employees with id's 0 & 1
    >>>>>>>>> var emp = e.employee.(@id == 1).name; // name of employee with id 1
    >>>>>>>>> 
    >>>>>>>>> The effect of the filtering predicate is similar to SQL’s WHERE clause or XPath’s filtering predicates.
    >>>>>>>>> For example, the statement:
    >>>>>>>>> 
    >>>>>>>>> // get the two employees with ids 0 and 1 using a predicate
    >>>>>>>>> var twoEmployees = e..employee.(@id == 0 || @id == 1);
    >>>>>>>>> 
    >>>>>>>>> produces the same result as the following set of statements:
    >>>>>>>>> // get the two employees with the ids 0 and 1 using a for loop
    >>>>>>>>> var i = 0;
    >>>>>>>>> var twoEmployees = new XMLList();
    >>>>>>>>> for each (var p in e..employee) {
    >>>>>>>>> with (p) {
    >>>>>>>>> if (@id == 0 || @id == 1) {
    >>>>>>>>> twoEmployees[i++] = p;
    >>>>>>>>> }
    >>>>>>>>> }
    >>>>>>>>> }
    >>>>>>>> 
    >>>>>>>> The question is what is "the front of the scope chain of the current execution context”? I’m pretty sure that means the start of sub-expressions. I don’t see how that can apply to the right-hand of comparison expressions. There is nothing in the spec about figuring out if a part of an expression is referring to XML or XMLList.
    >>>>>>>> 
    >>>>>>>>> On Aug 7, 2018, at 9:45 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >>>>>>>>> 
    >>>>>>>>> I don't get what portion of the spec has to do with whether we append "node" to various expressions.  IMO, the changes I made only affect 6b.  6a is handled by generating a function with "node" as the parameter (because node is list[i] in the spec).  The task in 6b is to correctly evaluate any e4x filter expression. I'm not sure what the limits are on what you can have in a filter expression, but if you can have just plain "@app" anywhere in the filter expression, I don't believe scoping rules would know to apply that to the "node" parameter without generating the "node" before "@app".
    >>>>>>>>> 
    >>>>>>>>> There is a chance that the Flex Compiler was using "magic" to generate the "node" and really should have reported an error.  I do remember being told that the filter function can be "anything".  Even:
    >>>>>>>>> (var foo:int = @app.length(); foo > @bar.length())  
    >>>>>>>>> 
    >>>>>>>>> If there are actual rules in the spec about evaluating the expression, that might apply to how we handle these expressions, otherwise I think the right thing is to resolve each expression and if the expression does not resolve to anything else, assume that it applies to the node.   I know the logic in EmitterUtils.writeE4xFilterNode isn't covering all cases.  It is trying to see what the expression resolves to, and returns false for known conditions (like a member of a class).  Just make it return false for your case (and feel free to add that case to the tests).  Eventually we'll have enough cases to either call it "good enough" or figure out a better way to determine when the expression applies to "node".
    >>>>>>>>> 
    >>>>>>>>> My 2 cents,
    >>>>>>>>> -Alex
    >>>>>>>>> 
    >>>>>>>>> On 8/6/18, 11:20 PM, "Harbs" <ha...@gmail.com> wrote:
    >>>>>>>>> 
    >>>>>>>>> I just looked at the spec. I think it’s correct to append “node” to the first statement of the expression only. The only exception seems to be expressions which use boolean expressions (i.e. || or &&) in which case each piece of the boolean expression should be considered a self-contained expression. So in your example, there are really two filter expressions:
    >>>>>>>>> 1. hasOwnProperty("@app”)
    >>>>>>>>> 2. @app.length() > 0
    >>>>>>>>> 
    >>>>>>>>> Both of those should have node appended to the front, but nothing else.
    >>>>>>>>> 
    >>>>>>>>> Here’s the relevant semantics in the spec (the important bit being 6a):
    >>>>>>>>> 
    >>>>>>>>>> 6. For i = 0 to list.[[Length]]-1
    >>>>>>>>>> a. Add list[i] to the front of the scope chain
    >>>>>>>>>> b. Let ref be the result of evaluating Expression using the augmented scope chain of step 6a
    >>>>>>>>>> c. Let match = ToBoolean(GetValue(ref))
    >>>>>>>>>> d. Remove list[i] from the front of the scope chain
    >>>>>>>>>> e. If (match == true), call the [[Append]] method of r with argument list[i]
    >>>>>>>>>> 7. Return r
    >>>>>>>>> 
    >>>>>>>>> Makes sense?
    >>>>>>>>> 
    >>>>>>>>> Harbs
    >>>>>>>>> 
    >>>>>>>>>> On Aug 7, 2018, at 1:39 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >>>>>>>>>> 
    >>>>>>>>>> In porting Tour De Flex, there were patterns like this (explorerTree is XML):
    >>>>>>>>>> 
    >>>>>>>>>> explorerTree..node.(hasOwnProperty("@app") && @app.length() > 0)
    >>>>>>>>>> 
    >>>>>>>>>> The compiler logic before I made any changes yesterday just assumed that the first expression was a reference to the node parameter but other expressions were not, but it looks like the expression "@app.length()" was allowed in Flex as a reference to the node.  So I think the compiler has to determine what expressions evaluate to "nothing" which implies they are references to the node, and what did resolve to something.  This is all new logic and I don't know how to determine all of the test cases up front, so we'll have to keep tuning it as we find patterns that don't work as we want them to.
    >>>>>>>>>> 
    >>>>>>>>>> In your case, if the expression resolves to a VariableDefinition, that probably means that isn't a reference to node.  Not exactly sure, so you should debug into it to see what the node pattern is and return false.
    >>>>>>>>>> 
    >>>>>>>>>> Thanks,
    >>>>>>>>>> -Alex
    >>>>>>>>>> 
    >>>>>>>>>> On 8/6/18, 3:28 PM, "Harbs" <ha...@gmail.com> wrote:
    >>>>>>>>>> 
    >>>>>>>>>> Doesn’t it always need to be a method for it to reference the node?
    >>>>>>>>>> 
    >>>>>>>>>> I.e. child() should be node.child(), but foo.baz would not.
    >>>>>>>>>> 
    >>>>>>>>>>> On Aug 7, 2018, at 1:12 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >>>>>>>>>>> 
    >>>>>>>>>>> Yep, we need more intelligent understanding of when a reference is to the node or not.
    >>>>>>>>>>> 
    >>>>>>>>>>> Debug into EmitterUtils.writeE4xFilterNode and figure out the node pattern you need.
    >>>>>>>>>>> 
    >>>>>>>>>>> -Alex
    >>>>>>>>>>> 
    >>>>>>>>>>> On 8/6/18, 3:09 PM, "Harbs" <ha...@gmail.com> wrote:
    >>>>>>>>>>> 
    >>>>>>>>>>> var folderFolders:XMLList = assetXML.folder.(child('key').indexOf(folder.key) == 0);
    >>>>>>>>>>> var folderImages:XMLList = assetXML.image.(child('key').indexOf(folder.key) == 0);
    >>>>>>>>>>> 
    >>>>>>>>>>> Is now compiled as:
    >>>>>>>>>>> 
    >>>>>>>>>>> var /** @type {XMLList} */ folderFolders = this.assetXML.child('folder').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
    >>>>>>>>>>> var /** @type {XMLList} */ folderImages = this.assetXML.child('image').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
    >>>>>>>>>>> 
    >>>>>>>>>>> “node.folder.key” is not correct. “folder” is a local variable of an un related object type.
    >>>>>>>>>>> 
    >>>>>>>>>>> I assume this broke with the recent XML filter changes.
    >>>>>>>>>>> 
    >>>>>>>>>>> Harbs
    
    


Re: XML filters broke

Posted by Harbs <ha...@gmail.com>.
It looks like we have duplicate classes in Storage and Network. I think we need to pick which package these classes belong in.


> On Aug 9, 2018, at 12:38 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
> 
> There's an IDataInput/IDataOutput in the Network.swc in the develop branch that would be useful to have in the feature/MXRoyale branch.  I don't want to stop to do a full merge right now.
> 
> -Alex
> 
> On 8/8/18, 2:36 PM, "Harbs" <harbs.lists@gmail.com <ma...@gmail.com>> wrote:
> 
>    What’s the issue with IDataInput/IDataOutput? Cherrypicked from where?
> 
>> On Aug 8, 2018, at 11:48 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>> 
>> Won’t know until we try it.  I'll adjust XMLList as needed.  I have an actual test case with Tour De Flex to work with.
>> 
>> If you have time to cherrypick IDataInput/IDataOutput for our users that would be helpful.
>> 
>> Thanks,
>> -Alex
>> 
>> On 8/8/18, 1:31 PM, "Harbs" <ha...@gmail.com> wrote:
>> 
>>   Are you sure the logic to reassign this will work here?
>> 
>>   I’m willing to rewrite the code in XMLList to use call if you think it’ll make things easier in the compiler…
>> 
>>> On Aug 8, 2018, at 11:03 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>> 
>>> 
>>> 
>>> On 8/8/18, 12:59 AM, "Harbs" <harbs.lists@gmail.com <ma...@gmail.com>> wrote:
>>> 
>>>  Does “this” in call/apply even work for a function which is not a prototype function? I thought in that case “this” is the global context.
>>> 
>>> From my testing, the 'this' can be re-assigned as we want it.
>>> 
>>>  I think 6a is kind of ambiguous. Why do you think there’s a difference between the following (other than avoiding ambiguous this references)?
>>> 
>>> Because there is already code that distinguishes when 'this' is supposed to be used.  So we should use it instead of crafting a whole other set of code that has a more difficult problem to solve, like whether an expression is relative to a parameter and if so, which parameter?
>>> 
>>> My 2 cents,
>>> -Alex
>>> 
>>>  function() { return (over40(parseInt(this.age))) }
>>>  and 
>>>  function(node) { return (over40(parseInt(node.age))) }
>>> 
>>>  Although in fact, I think it would need to be:
>>> 
>>>  function(node) { return (over40(parseInt(node.child(“age”)))) }
>>> 
>>>> On Aug 8, 2018, at 10:33 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>> 
>>>> EmitterUtils.writeThis seems to be working ok.  I think it would be better/correct to use it here.  I'm not sure if node as a parameter creates the same scope chain as node being the this pointer.  I think no, I don't think parameters are involved in lexical scoping.   IMO, 6a in the spec is saying we should make node the 'this' pointer in JS.
>>>> 
>>>> My 2 cents,
>>>> -Alex
>>>> 
>>>> On 8/7/18, 10:54 AM, "Harbs" <ha...@gmail.com> wrote:
>>>> 
>>>> I’m not following you. Wouldn’t we need the same logic to figure out where to insert “this”? I’m not sure what practical difference there would be between “node" and “this”, other than using apply or call. Passing in the XML node seems cleaner to me.
>>>> 
>>>>> On Aug 7, 2018, at 6:50 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>>> 
>>>>> Yup.  After thinking about it some more, it occurs to me that we took the wrong starting point.  Right now code like:
>>>>> 
>>>>> over40(parseInt(age))
>>>>> 
>>>>> Results in:
>>>>> 
>>>>> function(node) { return (over40(parseInt(age))) }
>>>>> 
>>>>> And then the XML filter calls that function passing itself in as the node.
>>>>> 
>>>>> And this discussion has been about trying to figure out where to add the "node" parameter.  But now I think that 6a in the spec is really saying that the 'this' pointer should be the node.  We should transpile that filter expression like any other function body but assume it is a function run in the context of the node, like a new method on XML/XMLList, or maybe more like an anonymous function.
>>>>> 
>>>>> So if I'm right, then the output should be:
>>>>> 
>>>>> function() { return (over40(parseInt(this.age))) }
>>>>> 
>>>>> This is what the transpiler would have output if you had subclassed XML and added this method to it.  And then the code in XML.SWC that applies the filter has to use Function.apply/call passing the node as the 'this' pointer.
>>>>> 
>>>>> If we do that, then the EmitterUtils.writeE4xFilterNode would go away, and JSRoyaleEmitter.emitE4xFilter would temporarily change the model.currentClass and maybe a few other things to reference an XML object.
>>>>> 
>>>>> Thoughts?
>>>>> -Alex
>>>>> 
>>>>> PS: Regarding adding tests, the filter tests have two variables.  "var a" sets up the XML, "var b" is the result of the filter.  getVariable returns the nodes for "a" then we go get child(1) which is "b" and then emit it to see what we get.
>>>>> 
>>>>> On 8/7/18, 3:51 AM, "Harbs" <harbs.lists@gmail.com <ma...@gmail.com>> wrote:
>>>>> 
>>>>> I’m also pretty sure that the following from Mozilla’s page[1] will not work correctly:
>>>>> 
>>>>> var people = <people>
>>>>>  <person>
>>>>>    <name>Bob</name>
>>>>>    <age>32</age>
>>>>>  </person>
>>>>>  <person>
>>>>>    <name>Joe</name>
>>>>>    <age>46</age>
>>>>>  </person>
>>>>> </people>;
>>>>> 
>>>>> function over40(i) {
>>>>>    return i > 40;
>>>>> }
>>>>> 
>>>>> alert(people.person.(over40(parseInt(age))).name); // Alerts Joe
>>>>> 
>>>>> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cc0654eacbc3c42ed040708d5fd770444%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693609968754943&amp;sdata=ZscyrBFzYFhQKpPQaS316AK0%2Bs8c6aM6Ir1KDRa0gQ8%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cc0654eacbc3c42ed040708d5fd770444%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693609968754943&amp;sdata=ZscyrBFzYFhQKpPQaS316AK0%2Bs8c6aM6Ir1KDRa0gQ8%3D&amp;reserved=0> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cc0654eacbc3c42ed040708d5fd770444%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693609968754943&amp;sdata=ZscyrBFzYFhQKpPQaS316AK0%2Bs8c6aM6Ir1KDRa0gQ8%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cc0654eacbc3c42ed040708d5fd770444%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693609968754943&amp;sdata=ZscyrBFzYFhQKpPQaS316AK0%2Bs8c6aM6Ir1KDRa0gQ8%3D&amp;reserved=0>> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cc0654eacbc3c42ed040708d5fd770444%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693609968754943&amp;sdata=ZscyrBFzYFhQKpPQaS316AK0%2Bs8c6aM6Ir1KDRa0gQ8%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cc0654eacbc3c42ed040708d5fd770444%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693609968754943&amp;sdata=ZscyrBFzYFhQKpPQaS316AK0%2Bs8c6aM6Ir1KDRa0gQ8%3D&amp;reserved=0> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cc0654eacbc3c42ed040708d5fd770444%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693609968754943&amp;sdata=ZscyrBFzYFhQKpPQaS316AK0%2Bs8c6aM6Ir1KDRa0gQ8%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cc0654eacbc3c42ed040708d5fd770444%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693609968754943&amp;sdata=ZscyrBFzYFhQKpPQaS316AK0%2Bs8c6aM6Ir1KDRa0gQ8%3D&amp;reserved=0>>> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cc0654eacbc3c42ed040708d5fd770444%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693609968754943&amp;sdata=ZscyrBFzYFhQKpPQaS316AK0%2Bs8c6aM6Ir1KDRa0gQ8%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cc0654eacbc3c42ed040708d5fd770444%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693609968754943&amp;sdata=ZscyrBFzYFhQKpPQaS316AK0%2Bs8c6aM6Ir1KDRa0gQ8%3D&amp;reserved=0> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cc0654eacbc3c42ed040708d5fd770444%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693609968754943&amp;sdata=ZscyrBFzYFhQKpPQaS316AK0%2Bs8c6aM6Ir1KDRa0gQ8%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cc0654eacbc3c42ed040708d5fd770444%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693609968754943&amp;sdata=ZscyrBFzYFhQKpPQaS316AK0%2Bs8c6aM6Ir1KDRa0gQ8%3D&amp;reserved=0>> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cc0654eacbc3c42ed040708d5fd770444%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693609968754943&amp;sdata=ZscyrBFzYFhQKpPQaS316AK0%2Bs8c6aM6Ir1KDRa0gQ8%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cc0654eacbc3c42ed040708d5fd770444%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693609968754943&amp;sdata=ZscyrBFzYFhQKpPQaS316AK0%2Bs8c6aM6Ir1KDRa0gQ8%3D&amp;reserved=0> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cc0654eacbc3c42ed040708d5fd770444%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693609968764948&amp;sdata=O9JpvK3CuJqZhDZlq2uTZg5ymXT0NZdok1uj6ugRexE%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cc0654eacbc3c42ed040708d5fd770444%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693609968764948&amp;sdata=O9JpvK3CuJqZhDZlq2uTZg5ymXT0NZdok1uj6ugRexE%3D&amp;reserved=0>>>>
>>>>> 
>>>>>> On Aug 7, 2018, at 1:41 PM, Harbs <ha...@gmail.com> wrote:
>>>>>> 
>>>>>> OK. I fixed the issue, but there’s a couple of loose ends:
>>>>>> 
>>>>>> 1. I don’t know how to add unit tests for these cases. In the current unit tests, I see “getNode” and “getVariable” being used. I don’t know the logic in setting up tests.
>>>>>> 2. I’m not quite sure what "parentNode.getChild(0)” does. What is the parent node and will this cause my second case of e.employee.(1 == @id) to fail? Removing the check against firstChild caused the testXMLFilterWithAttribute test to fail because it prepended “node.” to “length()”.
>>>>>> 
>>>>>> P.S. I finally got debugging from Eclipse working on the compiler, so hopefully I’ll have a much easier time fixing compiler issues in the future. :-)
>>>>>> 
>>>>>> Thanks,
>>>>>> Harbs
>>>>>> 
>>>>>>> On Aug 7, 2018, at 10:51 AM, Harbs <ha...@gmail.com> wrote:
>>>>>>> 
>>>>>>> Well, it looks like I was wrong.
>>>>>>> 
>>>>>>> I just tested the following in Flash, and then both give the same results (i.e. return the attribute):
>>>>>>> 
>>>>>>> var emp = e.employee.(@id == 1).@name; // name of employee with id 1
>>>>>>> var foo = e.employee.(1 == @id).@name; // name of employee with id 1
>>>>>>> 
>>>>>>>> On Aug 7, 2018, at 10:27 AM, Harbs <ha...@gmail.com> wrote:
>>>>>>>> 
>>>>>>>> Your example does not seem to be right to me.
>>>>>>>> 
>>>>>>>> Here’s the overview of how filters are supposed to work from the spec:
>>>>>>>> 
>>>>>>>>> Overview
>>>>>>>>> When the left operand evaluates to an XML object, the filtering predicate adds the left operand to the front of the scope chain of the current execution context, evaluates the Expression with the augmented scope chain, converts the result to a Boolean value, then restores the scope chain. If the result is true, the filtering predicate returns an XMLList containing the left operand. Otherwise it returns an empty XMLList.
>>>>>>>>> When the left operand is an XMLList, the filtering predicate is applied to each XML object in the XMLList in order using the XML object as the left operand and the Expression as the right operand. It concatenates the results and returns them as a single XMLList containing all the XML properties for which the result was true. For example,
>>>>>>>>> 
>>>>>>>>> var john = e.employee.(name == "John"); // employees with name John
>>>>>>>>> var twoemployees = e.employee.(@id == 0 || @id == 1); // employees with id's 0 & 1
>>>>>>>>> var emp = e.employee.(@id == 1).name; // name of employee with id 1
>>>>>>>>> 
>>>>>>>>> The effect of the filtering predicate is similar to SQL’s WHERE clause or XPath’s filtering predicates.
>>>>>>>>> For example, the statement:
>>>>>>>>> 
>>>>>>>>> // get the two employees with ids 0 and 1 using a predicate
>>>>>>>>> var twoEmployees = e..employee.(@id == 0 || @id == 1);
>>>>>>>>> 
>>>>>>>>> produces the same result as the following set of statements:
>>>>>>>>> // get the two employees with the ids 0 and 1 using a for loop
>>>>>>>>> var i = 0;
>>>>>>>>> var twoEmployees = new XMLList();
>>>>>>>>> for each (var p in e..employee) {
>>>>>>>>> with (p) {
>>>>>>>>> if (@id == 0 || @id == 1) {
>>>>>>>>> twoEmployees[i++] = p;
>>>>>>>>> }
>>>>>>>>> }
>>>>>>>>> }
>>>>>>>> 
>>>>>>>> The question is what is "the front of the scope chain of the current execution context”? I’m pretty sure that means the start of sub-expressions. I don’t see how that can apply to the right-hand of comparison expressions. There is nothing in the spec about figuring out if a part of an expression is referring to XML or XMLList.
>>>>>>>> 
>>>>>>>>> On Aug 7, 2018, at 9:45 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>>>>>>> 
>>>>>>>>> I don't get what portion of the spec has to do with whether we append "node" to various expressions.  IMO, the changes I made only affect 6b.  6a is handled by generating a function with "node" as the parameter (because node is list[i] in the spec).  The task in 6b is to correctly evaluate any e4x filter expression. I'm not sure what the limits are on what you can have in a filter expression, but if you can have just plain "@app" anywhere in the filter expression, I don't believe scoping rules would know to apply that to the "node" parameter without generating the "node" before "@app".
>>>>>>>>> 
>>>>>>>>> There is a chance that the Flex Compiler was using "magic" to generate the "node" and really should have reported an error.  I do remember being told that the filter function can be "anything".  Even:
>>>>>>>>> (var foo:int = @app.length(); foo > @bar.length())  
>>>>>>>>> 
>>>>>>>>> If there are actual rules in the spec about evaluating the expression, that might apply to how we handle these expressions, otherwise I think the right thing is to resolve each expression and if the expression does not resolve to anything else, assume that it applies to the node.   I know the logic in EmitterUtils.writeE4xFilterNode isn't covering all cases.  It is trying to see what the expression resolves to, and returns false for known conditions (like a member of a class).  Just make it return false for your case (and feel free to add that case to the tests).  Eventually we'll have enough cases to either call it "good enough" or figure out a better way to determine when the expression applies to "node".
>>>>>>>>> 
>>>>>>>>> My 2 cents,
>>>>>>>>> -Alex
>>>>>>>>> 
>>>>>>>>> On 8/6/18, 11:20 PM, "Harbs" <ha...@gmail.com> wrote:
>>>>>>>>> 
>>>>>>>>> I just looked at the spec. I think it’s correct to append “node” to the first statement of the expression only. The only exception seems to be expressions which use boolean expressions (i.e. || or &&) in which case each piece of the boolean expression should be considered a self-contained expression. So in your example, there are really two filter expressions:
>>>>>>>>> 1. hasOwnProperty("@app”)
>>>>>>>>> 2. @app.length() > 0
>>>>>>>>> 
>>>>>>>>> Both of those should have node appended to the front, but nothing else.
>>>>>>>>> 
>>>>>>>>> Here’s the relevant semantics in the spec (the important bit being 6a):
>>>>>>>>> 
>>>>>>>>>> 6. For i = 0 to list.[[Length]]-1
>>>>>>>>>> a. Add list[i] to the front of the scope chain
>>>>>>>>>> b. Let ref be the result of evaluating Expression using the augmented scope chain of step 6a
>>>>>>>>>> c. Let match = ToBoolean(GetValue(ref))
>>>>>>>>>> d. Remove list[i] from the front of the scope chain
>>>>>>>>>> e. If (match == true), call the [[Append]] method of r with argument list[i]
>>>>>>>>>> 7. Return r
>>>>>>>>> 
>>>>>>>>> Makes sense?
>>>>>>>>> 
>>>>>>>>> Harbs
>>>>>>>>> 
>>>>>>>>>> On Aug 7, 2018, at 1:39 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>>>>>>>> 
>>>>>>>>>> In porting Tour De Flex, there were patterns like this (explorerTree is XML):
>>>>>>>>>> 
>>>>>>>>>> explorerTree..node.(hasOwnProperty("@app") && @app.length() > 0)
>>>>>>>>>> 
>>>>>>>>>> The compiler logic before I made any changes yesterday just assumed that the first expression was a reference to the node parameter but other expressions were not, but it looks like the expression "@app.length()" was allowed in Flex as a reference to the node.  So I think the compiler has to determine what expressions evaluate to "nothing" which implies they are references to the node, and what did resolve to something.  This is all new logic and I don't know how to determine all of the test cases up front, so we'll have to keep tuning it as we find patterns that don't work as we want them to.
>>>>>>>>>> 
>>>>>>>>>> In your case, if the expression resolves to a VariableDefinition, that probably means that isn't a reference to node.  Not exactly sure, so you should debug into it to see what the node pattern is and return false.
>>>>>>>>>> 
>>>>>>>>>> Thanks,
>>>>>>>>>> -Alex
>>>>>>>>>> 
>>>>>>>>>> On 8/6/18, 3:28 PM, "Harbs" <ha...@gmail.com> wrote:
>>>>>>>>>> 
>>>>>>>>>> Doesn’t it always need to be a method for it to reference the node?
>>>>>>>>>> 
>>>>>>>>>> I.e. child() should be node.child(), but foo.baz would not.
>>>>>>>>>> 
>>>>>>>>>>> On Aug 7, 2018, at 1:12 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>>>>>>>>> 
>>>>>>>>>>> Yep, we need more intelligent understanding of when a reference is to the node or not.
>>>>>>>>>>> 
>>>>>>>>>>> Debug into EmitterUtils.writeE4xFilterNode and figure out the node pattern you need.
>>>>>>>>>>> 
>>>>>>>>>>> -Alex
>>>>>>>>>>> 
>>>>>>>>>>> On 8/6/18, 3:09 PM, "Harbs" <ha...@gmail.com> wrote:
>>>>>>>>>>> 
>>>>>>>>>>> var folderFolders:XMLList = assetXML.folder.(child('key').indexOf(folder.key) == 0);
>>>>>>>>>>> var folderImages:XMLList = assetXML.image.(child('key').indexOf(folder.key) == 0);
>>>>>>>>>>> 
>>>>>>>>>>> Is now compiled as:
>>>>>>>>>>> 
>>>>>>>>>>> var /** @type {XMLList} */ folderFolders = this.assetXML.child('folder').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
>>>>>>>>>>> var /** @type {XMLList} */ folderImages = this.assetXML.child('image').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
>>>>>>>>>>> 
>>>>>>>>>>> “node.folder.key” is not correct. “folder” is a local variable of an un related object type.
>>>>>>>>>>> 
>>>>>>>>>>> I assume this broke with the recent XML filter changes.
>>>>>>>>>>> 
>>>>>>>>>>> Harbs


Re: XML filters broke

Posted by Alex Harui <ah...@adobe.com.INVALID>.
There's an IDataInput/IDataOutput in the Network.swc in the develop branch that would be useful to have in the feature/MXRoyale branch.  I don't want to stop to do a full merge right now.

-Alex

On 8/8/18, 2:36 PM, "Harbs" <ha...@gmail.com> wrote:

    What’s the issue with IDataInput/IDataOutput? Cherrypicked from where?
    
    > On Aug 8, 2018, at 11:48 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    > 
    > Won’t know until we try it.  I'll adjust XMLList as needed.  I have an actual test case with Tour De Flex to work with.
    > 
    > If you have time to cherrypick IDataInput/IDataOutput for our users that would be helpful.
    > 
    > Thanks,
    > -Alex
    > 
    > On 8/8/18, 1:31 PM, "Harbs" <ha...@gmail.com> wrote:
    > 
    >    Are you sure the logic to reassign this will work here?
    > 
    >    I’m willing to rewrite the code in XMLList to use call if you think it’ll make things easier in the compiler…
    > 
    >> On Aug 8, 2018, at 11:03 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >> 
    >> 
    >> 
    >> On 8/8/18, 12:59 AM, "Harbs" <harbs.lists@gmail.com <ma...@gmail.com>> wrote:
    >> 
    >>   Does “this” in call/apply even work for a function which is not a prototype function? I thought in that case “this” is the global context.
    >> 
    >> From my testing, the 'this' can be re-assigned as we want it.
    >> 
    >>   I think 6a is kind of ambiguous. Why do you think there’s a difference between the following (other than avoiding ambiguous this references)?
    >> 
    >> Because there is already code that distinguishes when 'this' is supposed to be used.  So we should use it instead of crafting a whole other set of code that has a more difficult problem to solve, like whether an expression is relative to a parameter and if so, which parameter?
    >> 
    >> My 2 cents,
    >> -Alex
    >> 
    >>   function() { return (over40(parseInt(this.age))) }
    >>   and 
    >>   function(node) { return (over40(parseInt(node.age))) }
    >> 
    >>   Although in fact, I think it would need to be:
    >> 
    >>   function(node) { return (over40(parseInt(node.child(“age”)))) }
    >> 
    >>> On Aug 8, 2018, at 10:33 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >>> 
    >>> EmitterUtils.writeThis seems to be working ok.  I think it would be better/correct to use it here.  I'm not sure if node as a parameter creates the same scope chain as node being the this pointer.  I think no, I don't think parameters are involved in lexical scoping.   IMO, 6a in the spec is saying we should make node the 'this' pointer in JS.
    >>> 
    >>> My 2 cents,
    >>> -Alex
    >>> 
    >>> On 8/7/18, 10:54 AM, "Harbs" <ha...@gmail.com> wrote:
    >>> 
    >>>  I’m not following you. Wouldn’t we need the same logic to figure out where to insert “this”? I’m not sure what practical difference there would be between “node" and “this”, other than using apply or call. Passing in the XML node seems cleaner to me.
    >>> 
    >>>> On Aug 7, 2018, at 6:50 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >>>> 
    >>>> Yup.  After thinking about it some more, it occurs to me that we took the wrong starting point.  Right now code like:
    >>>> 
    >>>> over40(parseInt(age))
    >>>> 
    >>>> Results in:
    >>>> 
    >>>> function(node) { return (over40(parseInt(age))) }
    >>>> 
    >>>> And then the XML filter calls that function passing itself in as the node.
    >>>> 
    >>>> And this discussion has been about trying to figure out where to add the "node" parameter.  But now I think that 6a in the spec is really saying that the 'this' pointer should be the node.  We should transpile that filter expression like any other function body but assume it is a function run in the context of the node, like a new method on XML/XMLList, or maybe more like an anonymous function.
    >>>> 
    >>>> So if I'm right, then the output should be:
    >>>> 
    >>>> function() { return (over40(parseInt(this.age))) }
    >>>> 
    >>>> This is what the transpiler would have output if you had subclassed XML and added this method to it.  And then the code in XML.SWC that applies the filter has to use Function.apply/call passing the node as the 'this' pointer.
    >>>> 
    >>>> If we do that, then the EmitterUtils.writeE4xFilterNode would go away, and JSRoyaleEmitter.emitE4xFilter would temporarily change the model.currentClass and maybe a few other things to reference an XML object.
    >>>> 
    >>>> Thoughts?
    >>>> -Alex
    >>>> 
    >>>> PS: Regarding adding tests, the filter tests have two variables.  "var a" sets up the XML, "var b" is the result of the filter.  getVariable returns the nodes for "a" then we go get child(1) which is "b" and then emit it to see what we get.
    >>>> 
    >>>> On 8/7/18, 3:51 AM, "Harbs" <harbs.lists@gmail.com <ma...@gmail.com>> wrote:
    >>>> 
    >>>> I’m also pretty sure that the following from Mozilla’s page[1] will not work correctly:
    >>>> 
    >>>> var people = <people>
    >>>>   <person>
    >>>>     <name>Bob</name>
    >>>>     <age>32</age>
    >>>>   </person>
    >>>>   <person>
    >>>>     <name>Joe</name>
    >>>>     <age>46</age>
    >>>>   </person>
    >>>> </people>;
    >>>> 
    >>>> function over40(i) {
    >>>>     return i > 40;
    >>>> }
    >>>> 
    >>>> alert(people.person.(over40(parseInt(age))).name); // Alerts Joe
    >>>> 
    >>>> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cc0654eacbc3c42ed040708d5fd770444%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693609968754943&amp;sdata=ZscyrBFzYFhQKpPQaS316AK0%2Bs8c6aM6Ir1KDRa0gQ8%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cc0654eacbc3c42ed040708d5fd770444%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693609968754943&amp;sdata=ZscyrBFzYFhQKpPQaS316AK0%2Bs8c6aM6Ir1KDRa0gQ8%3D&amp;reserved=0> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cc0654eacbc3c42ed040708d5fd770444%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693609968754943&amp;sdata=ZscyrBFzYFhQKpPQaS316AK0%2Bs8c6aM6Ir1KDRa0gQ8%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cc0654eacbc3c42ed040708d5fd770444%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693609968754943&amp;sdata=ZscyrBFzYFhQKpPQaS316AK0%2Bs8c6aM6Ir1KDRa0gQ8%3D&amp;reserved=0>> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cc0654eacbc3c42ed040708d5fd770444%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693609968754943&amp;sdata=ZscyrBFzYFhQKpPQaS316AK0%2Bs8c6aM6Ir1KDRa0gQ8%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cc0654eacbc3c42ed040708d5fd770444%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693609968754943&amp;sdata=ZscyrBFzYFhQKpPQaS316AK0%2Bs8c6aM6Ir1KDRa0gQ8%3D&amp;reserved=0> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cc0654eacbc3c42ed040708d5fd770444%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693609968754943&amp;sdata=ZscyrBFzYFhQKpPQaS316AK0%2Bs8c6aM6Ir1KDRa0gQ8%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7Cc0654eacbc3c42ed040708d5fd770444%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693609968764948&amp;sdata=O9JpvK3CuJqZhDZlq2uTZg5ymXT0NZdok1uj6ugRexE%3D&amp;reserved=0>>>
    >>>> 
    >>>>> On Aug 7, 2018, at 1:41 PM, Harbs <ha...@gmail.com> wrote:
    >>>>> 
    >>>>> OK. I fixed the issue, but there’s a couple of loose ends:
    >>>>> 
    >>>>> 1. I don’t know how to add unit tests for these cases. In the current unit tests, I see “getNode” and “getVariable” being used. I don’t know the logic in setting up tests.
    >>>>> 2. I’m not quite sure what "parentNode.getChild(0)” does. What is the parent node and will this cause my second case of e.employee.(1 == @id) to fail? Removing the check against firstChild caused the testXMLFilterWithAttribute test to fail because it prepended “node.” to “length()”.
    >>>>> 
    >>>>> P.S. I finally got debugging from Eclipse working on the compiler, so hopefully I’ll have a much easier time fixing compiler issues in the future. :-)
    >>>>> 
    >>>>> Thanks,
    >>>>> Harbs
    >>>>> 
    >>>>>> On Aug 7, 2018, at 10:51 AM, Harbs <ha...@gmail.com> wrote:
    >>>>>> 
    >>>>>> Well, it looks like I was wrong.
    >>>>>> 
    >>>>>> I just tested the following in Flash, and then both give the same results (i.e. return the attribute):
    >>>>>> 
    >>>>>> var emp = e.employee.(@id == 1).@name; // name of employee with id 1
    >>>>>> var foo = e.employee.(1 == @id).@name; // name of employee with id 1
    >>>>>> 
    >>>>>>> On Aug 7, 2018, at 10:27 AM, Harbs <ha...@gmail.com> wrote:
    >>>>>>> 
    >>>>>>> Your example does not seem to be right to me.
    >>>>>>> 
    >>>>>>> Here’s the overview of how filters are supposed to work from the spec:
    >>>>>>> 
    >>>>>>>> Overview
    >>>>>>>> When the left operand evaluates to an XML object, the filtering predicate adds the left operand to the front of the scope chain of the current execution context, evaluates the Expression with the augmented scope chain, converts the result to a Boolean value, then restores the scope chain. If the result is true, the filtering predicate returns an XMLList containing the left operand. Otherwise it returns an empty XMLList.
    >>>>>>>> When the left operand is an XMLList, the filtering predicate is applied to each XML object in the XMLList in order using the XML object as the left operand and the Expression as the right operand. It concatenates the results and returns them as a single XMLList containing all the XML properties for which the result was true. For example,
    >>>>>>>> 
    >>>>>>>> var john = e.employee.(name == "John"); // employees with name John
    >>>>>>>> var twoemployees = e.employee.(@id == 0 || @id == 1); // employees with id's 0 & 1
    >>>>>>>> var emp = e.employee.(@id == 1).name; // name of employee with id 1
    >>>>>>>> 
    >>>>>>>> The effect of the filtering predicate is similar to SQL’s WHERE clause or XPath’s filtering predicates.
    >>>>>>>> For example, the statement:
    >>>>>>>> 
    >>>>>>>> // get the two employees with ids 0 and 1 using a predicate
    >>>>>>>> var twoEmployees = e..employee.(@id == 0 || @id == 1);
    >>>>>>>> 
    >>>>>>>> produces the same result as the following set of statements:
    >>>>>>>> // get the two employees with the ids 0 and 1 using a for loop
    >>>>>>>> var i = 0;
    >>>>>>>> var twoEmployees = new XMLList();
    >>>>>>>> for each (var p in e..employee) {
    >>>>>>>> with (p) {
    >>>>>>>> if (@id == 0 || @id == 1) {
    >>>>>>>> twoEmployees[i++] = p;
    >>>>>>>> }
    >>>>>>>> }
    >>>>>>>> }
    >>>>>>> 
    >>>>>>> The question is what is "the front of the scope chain of the current execution context”? I’m pretty sure that means the start of sub-expressions. I don’t see how that can apply to the right-hand of comparison expressions. There is nothing in the spec about figuring out if a part of an expression is referring to XML or XMLList.
    >>>>>>> 
    >>>>>>>> On Aug 7, 2018, at 9:45 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >>>>>>>> 
    >>>>>>>> I don't get what portion of the spec has to do with whether we append "node" to various expressions.  IMO, the changes I made only affect 6b.  6a is handled by generating a function with "node" as the parameter (because node is list[i] in the spec).  The task in 6b is to correctly evaluate any e4x filter expression.  I'm not sure what the limits are on what you can have in a filter expression, but if you can have just plain "@app" anywhere in the filter expression, I don't believe scoping rules would know to apply that to the "node" parameter without generating the "node" before "@app".
    >>>>>>>> 
    >>>>>>>> There is a chance that the Flex Compiler was using "magic" to generate the "node" and really should have reported an error.  I do remember being told that the filter function can be "anything".  Even:
    >>>>>>>> (var foo:int = @app.length(); foo > @bar.length())  
    >>>>>>>> 
    >>>>>>>> If there are actual rules in the spec about evaluating the expression, that might apply to how we handle these expressions, otherwise I think the right thing is to resolve each expression and if the expression does not resolve to anything else, assume that it applies to the node.   I know the logic in EmitterUtils.writeE4xFilterNode isn't covering all cases.  It is trying to see what the expression resolves to, and returns false for known conditions (like a member of a class).  Just make it return false for your case (and feel free to add that case to the tests).  Eventually we'll have enough cases to either call it "good enough" or figure out a better way to determine when the expression applies to "node".
    >>>>>>>> 
    >>>>>>>> My 2 cents,
    >>>>>>>> -Alex
    >>>>>>>> 
    >>>>>>>> On 8/6/18, 11:20 PM, "Harbs" <ha...@gmail.com> wrote:
    >>>>>>>> 
    >>>>>>>> I just looked at the spec. I think it’s correct to append “node” to the first statement of the expression only. The only exception seems to be expressions which use boolean expressions (i.e. || or &&) in which case each piece of the boolean expression should be considered a self-contained expression. So in your example, there are really two filter expressions:
    >>>>>>>> 1. hasOwnProperty("@app”)
    >>>>>>>> 2. @app.length() > 0
    >>>>>>>> 
    >>>>>>>> Both of those should have node appended to the front, but nothing else.
    >>>>>>>> 
    >>>>>>>> Here’s the relevant semantics in the spec (the important bit being 6a):
    >>>>>>>> 
    >>>>>>>>> 6. For i = 0 to list.[[Length]]-1
    >>>>>>>>> a. Add list[i] to the front of the scope chain
    >>>>>>>>> b. Let ref be the result of evaluating Expression using the augmented scope chain of step 6a
    >>>>>>>>> c. Let match = ToBoolean(GetValue(ref))
    >>>>>>>>> d. Remove list[i] from the front of the scope chain
    >>>>>>>>> e. If (match == true), call the [[Append]] method of r with argument list[i]
    >>>>>>>>> 7. Return r
    >>>>>>>> 
    >>>>>>>> Makes sense?
    >>>>>>>> 
    >>>>>>>> Harbs
    >>>>>>>> 
    >>>>>>>>> On Aug 7, 2018, at 1:39 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >>>>>>>>> 
    >>>>>>>>> In porting Tour De Flex, there were patterns like this (explorerTree is XML):
    >>>>>>>>> 
    >>>>>>>>> explorerTree..node.(hasOwnProperty("@app") && @app.length() > 0)
    >>>>>>>>> 
    >>>>>>>>> The compiler logic before I made any changes yesterday just assumed that the first expression was a reference to the node parameter but other expressions were not, but it looks like the expression "@app.length()" was allowed in Flex as a reference to the node.  So I think the compiler has to determine what expressions evaluate to "nothing" which implies they are references to the node, and what did resolve to something.  This is all new logic and I don't know how to determine all of the test cases up front, so we'll have to keep tuning it as we find patterns that don't work as we want them to.
    >>>>>>>>> 
    >>>>>>>>> In your case, if the expression resolves to a VariableDefinition, that probably means that isn't a reference to node.  Not exactly sure, so you should debug into it to see what the node pattern is and return false.
    >>>>>>>>> 
    >>>>>>>>> Thanks,
    >>>>>>>>> -Alex
    >>>>>>>>> 
    >>>>>>>>> On 8/6/18, 3:28 PM, "Harbs" <ha...@gmail.com> wrote:
    >>>>>>>>> 
    >>>>>>>>> Doesn’t it always need to be a method for it to reference the node?
    >>>>>>>>> 
    >>>>>>>>> I.e. child() should be node.child(), but foo.baz would not.
    >>>>>>>>> 
    >>>>>>>>>> On Aug 7, 2018, at 1:12 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >>>>>>>>>> 
    >>>>>>>>>> Yep, we need more intelligent understanding of when a reference is to the node or not.
    >>>>>>>>>> 
    >>>>>>>>>> Debug into EmitterUtils.writeE4xFilterNode and figure out the node pattern you need.
    >>>>>>>>>> 
    >>>>>>>>>> -Alex
    >>>>>>>>>> 
    >>>>>>>>>> On 8/6/18, 3:09 PM, "Harbs" <ha...@gmail.com> wrote:
    >>>>>>>>>> 
    >>>>>>>>>> var folderFolders:XMLList = assetXML.folder.(child('key').indexOf(folder.key) == 0);
    >>>>>>>>>> var folderImages:XMLList = assetXML.image.(child('key').indexOf(folder.key) == 0);
    >>>>>>>>>> 
    >>>>>>>>>> Is now compiled as:
    >>>>>>>>>> 
    >>>>>>>>>> var /** @type {XMLList} */ folderFolders = this.assetXML.child('folder').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
    >>>>>>>>>> var /** @type {XMLList} */ folderImages = this.assetXML.child('image').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
    >>>>>>>>>> 
    >>>>>>>>>> “node.folder.key” is not correct. “folder” is a local variable of an un related object type.
    >>>>>>>>>> 
    >>>>>>>>>> I assume this broke with the recent XML filter changes.
    >>>>>>>>>> 
    >>>>>>>>>> Harbs
    > 
    > 
    > 
    
    


Re: XML filters broke

Posted by Harbs <ha...@gmail.com>.
What’s the issue with IDataInput/IDataOutput? Cherrypicked from where?

> On Aug 8, 2018, at 11:48 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
> 
> Won’t know until we try it.  I'll adjust XMLList as needed.  I have an actual test case with Tour De Flex to work with.
> 
> If you have time to cherrypick IDataInput/IDataOutput for our users that would be helpful.
> 
> Thanks,
> -Alex
> 
> On 8/8/18, 1:31 PM, "Harbs" <ha...@gmail.com> wrote:
> 
>    Are you sure the logic to reassign this will work here?
> 
>    I’m willing to rewrite the code in XMLList to use call if you think it’ll make things easier in the compiler…
> 
>> On Aug 8, 2018, at 11:03 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>> 
>> 
>> 
>> On 8/8/18, 12:59 AM, "Harbs" <harbs.lists@gmail.com <ma...@gmail.com>> wrote:
>> 
>>   Does “this” in call/apply even work for a function which is not a prototype function? I thought in that case “this” is the global context.
>> 
>> From my testing, the 'this' can be re-assigned as we want it.
>> 
>>   I think 6a is kind of ambiguous. Why do you think there’s a difference between the following (other than avoiding ambiguous this references)?
>> 
>> Because there is already code that distinguishes when 'this' is supposed to be used.  So we should use it instead of crafting a whole other set of code that has a more difficult problem to solve, like whether an expression is relative to a parameter and if so, which parameter?
>> 
>> My 2 cents,
>> -Alex
>> 
>>   function() { return (over40(parseInt(this.age))) }
>>   and 
>>   function(node) { return (over40(parseInt(node.age))) }
>> 
>>   Although in fact, I think it would need to be:
>> 
>>   function(node) { return (over40(parseInt(node.child(“age”)))) }
>> 
>>> On Aug 8, 2018, at 10:33 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>> 
>>> EmitterUtils.writeThis seems to be working ok.  I think it would be better/correct to use it here.  I'm not sure if node as a parameter creates the same scope chain as node being the this pointer.  I think no, I don't think parameters are involved in lexical scoping.   IMO, 6a in the spec is saying we should make node the 'this' pointer in JS.
>>> 
>>> My 2 cents,
>>> -Alex
>>> 
>>> On 8/7/18, 10:54 AM, "Harbs" <ha...@gmail.com> wrote:
>>> 
>>>  I’m not following you. Wouldn’t we need the same logic to figure out where to insert “this”? I’m not sure what practical difference there would be between “node" and “this”, other than using apply or call. Passing in the XML node seems cleaner to me.
>>> 
>>>> On Aug 7, 2018, at 6:50 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>> 
>>>> Yup.  After thinking about it some more, it occurs to me that we took the wrong starting point.  Right now code like:
>>>> 
>>>> over40(parseInt(age))
>>>> 
>>>> Results in:
>>>> 
>>>> function(node) { return (over40(parseInt(age))) }
>>>> 
>>>> And then the XML filter calls that function passing itself in as the node.
>>>> 
>>>> And this discussion has been about trying to figure out where to add the "node" parameter.  But now I think that 6a in the spec is really saying that the 'this' pointer should be the node.  We should transpile that filter expression like any other function body but assume it is a function run in the context of the node, like a new method on XML/XMLList, or maybe more like an anonymous function.
>>>> 
>>>> So if I'm right, then the output should be:
>>>> 
>>>> function() { return (over40(parseInt(this.age))) }
>>>> 
>>>> This is what the transpiler would have output if you had subclassed XML and added this method to it.  And then the code in XML.SWC that applies the filter has to use Function.apply/call passing the node as the 'this' pointer.
>>>> 
>>>> If we do that, then the EmitterUtils.writeE4xFilterNode would go away, and JSRoyaleEmitter.emitE4xFilter would temporarily change the model.currentClass and maybe a few other things to reference an XML object.
>>>> 
>>>> Thoughts?
>>>> -Alex
>>>> 
>>>> PS: Regarding adding tests, the filter tests have two variables.  "var a" sets up the XML, "var b" is the result of the filter.  getVariable returns the nodes for "a" then we go get child(1) which is "b" and then emit it to see what we get.
>>>> 
>>>> On 8/7/18, 3:51 AM, "Harbs" <harbs.lists@gmail.com <ma...@gmail.com>> wrote:
>>>> 
>>>> I’m also pretty sure that the following from Mozilla’s page[1] will not work correctly:
>>>> 
>>>> var people = <people>
>>>>   <person>
>>>>     <name>Bob</name>
>>>>     <age>32</age>
>>>>   </person>
>>>>   <person>
>>>>     <name>Joe</name>
>>>>     <age>46</age>
>>>>   </person>
>>>> </people>;
>>>> 
>>>> function over40(i) {
>>>>     return i > 40;
>>>> }
>>>> 
>>>> alert(people.person.(over40(parseInt(age))).name); // Alerts Joe
>>>> 
>>>> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C080f98afdf9d4bc823ed08d5fd6defd4%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693571001599413&amp;sdata=O7q%2Bzd7f1%2F8nIO64ZAGa9OcEfcaTGR0d5xj%2F7aAH6Ho%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C080f98afdf9d4bc823ed08d5fd6defd4%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693571001609423&amp;sdata=fVBJU6cb%2B5hcGWuIHVFVe8aeoZx4xLOYSmHP0bcctCI%3D&amp;reserved=0> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C080f98afdf9d4bc823ed08d5fd6defd4%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693571001609423&amp;sdata=fVBJU6cb%2B5hcGWuIHVFVe8aeoZx4xLOYSmHP0bcctCI%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C080f98afdf9d4bc823ed08d5fd6defd4%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693571001609423&amp;sdata=fVBJU6cb%2B5hcGWuIHVFVe8aeoZx4xLOYSmHP0bcctCI%3D&amp;reserved=0>> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C080f98afdf9d4bc823ed08d5fd6defd4%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693571001609423&amp;sdata=fVBJU6cb%2B5hcGWuIHVFVe8aeoZx4xLOYSmHP0bcctCI%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C080f98afdf9d4bc823ed08d5fd6defd4%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693571001609423&amp;sdata=fVBJU6cb%2B5hcGWuIHVFVe8aeoZx4xLOYSmHP0bcctCI%3D&amp;reserved=0> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C080f98afdf9d4bc823ed08d5fd6defd4%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693571001609423&amp;sdata=fVBJU6cb%2B5hcGWuIHVFVe8aeoZx4xLOYSmHP0bcctCI%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C080f98afdf9d4bc823ed08d5fd6defd4%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693571001609423&amp;sdata=fVBJU6cb%2B5hcGWuIHVFVe8aeoZx4xLOYSmHP0bcctCI%3D&amp;reserved=0>>>
>>>> 
>>>>> On Aug 7, 2018, at 1:41 PM, Harbs <ha...@gmail.com> wrote:
>>>>> 
>>>>> OK. I fixed the issue, but there’s a couple of loose ends:
>>>>> 
>>>>> 1. I don’t know how to add unit tests for these cases. In the current unit tests, I see “getNode” and “getVariable” being used. I don’t know the logic in setting up tests.
>>>>> 2. I’m not quite sure what "parentNode.getChild(0)” does. What is the parent node and will this cause my second case of e.employee.(1 == @id) to fail? Removing the check against firstChild caused the testXMLFilterWithAttribute test to fail because it prepended “node.” to “length()”.
>>>>> 
>>>>> P.S. I finally got debugging from Eclipse working on the compiler, so hopefully I’ll have a much easier time fixing compiler issues in the future. :-)
>>>>> 
>>>>> Thanks,
>>>>> Harbs
>>>>> 
>>>>>> On Aug 7, 2018, at 10:51 AM, Harbs <ha...@gmail.com> wrote:
>>>>>> 
>>>>>> Well, it looks like I was wrong.
>>>>>> 
>>>>>> I just tested the following in Flash, and then both give the same results (i.e. return the attribute):
>>>>>> 
>>>>>> var emp = e.employee.(@id == 1).@name; // name of employee with id 1
>>>>>> var foo = e.employee.(1 == @id).@name; // name of employee with id 1
>>>>>> 
>>>>>>> On Aug 7, 2018, at 10:27 AM, Harbs <ha...@gmail.com> wrote:
>>>>>>> 
>>>>>>> Your example does not seem to be right to me.
>>>>>>> 
>>>>>>> Here’s the overview of how filters are supposed to work from the spec:
>>>>>>> 
>>>>>>>> Overview
>>>>>>>> When the left operand evaluates to an XML object, the filtering predicate adds the left operand to the front of the scope chain of the current execution context, evaluates the Expression with the augmented scope chain, converts the result to a Boolean value, then restores the scope chain. If the result is true, the filtering predicate returns an XMLList containing the left operand. Otherwise it returns an empty XMLList.
>>>>>>>> When the left operand is an XMLList, the filtering predicate is applied to each XML object in the XMLList in order using the XML object as the left operand and the Expression as the right operand. It concatenates the results and returns them as a single XMLList containing all the XML properties for which the result was true. For example,
>>>>>>>> 
>>>>>>>> var john = e.employee.(name == "John"); // employees with name John
>>>>>>>> var twoemployees = e.employee.(@id == 0 || @id == 1); // employees with id's 0 & 1
>>>>>>>> var emp = e.employee.(@id == 1).name; // name of employee with id 1
>>>>>>>> 
>>>>>>>> The effect of the filtering predicate is similar to SQL’s WHERE clause or XPath’s filtering predicates.
>>>>>>>> For example, the statement:
>>>>>>>> 
>>>>>>>> // get the two employees with ids 0 and 1 using a predicate
>>>>>>>> var twoEmployees = e..employee.(@id == 0 || @id == 1);
>>>>>>>> 
>>>>>>>> produces the same result as the following set of statements:
>>>>>>>> // get the two employees with the ids 0 and 1 using a for loop
>>>>>>>> var i = 0;
>>>>>>>> var twoEmployees = new XMLList();
>>>>>>>> for each (var p in e..employee) {
>>>>>>>> with (p) {
>>>>>>>> if (@id == 0 || @id == 1) {
>>>>>>>> twoEmployees[i++] = p;
>>>>>>>> }
>>>>>>>> }
>>>>>>>> }
>>>>>>> 
>>>>>>> The question is what is "the front of the scope chain of the current execution context”? I’m pretty sure that means the start of sub-expressions. I don’t see how that can apply to the right-hand of comparison expressions. There is nothing in the spec about figuring out if a part of an expression is referring to XML or XMLList.
>>>>>>> 
>>>>>>>> On Aug 7, 2018, at 9:45 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>>>>>> 
>>>>>>>> I don't get what portion of the spec has to do with whether we append "node" to various expressions.  IMO, the changes I made only affect 6b.  6a is handled by generating a function with "node" as the parameter (because node is list[i] in the spec).  The task in 6b is to correctly evaluate any e4x filter expression.  I'm not sure what the limits are on what you can have in a filter expression, but if you can have just plain "@app" anywhere in the filter expression, I don't believe scoping rules would know to apply that to the "node" parameter without generating the "node" before "@app".
>>>>>>>> 
>>>>>>>> There is a chance that the Flex Compiler was using "magic" to generate the "node" and really should have reported an error.  I do remember being told that the filter function can be "anything".  Even:
>>>>>>>> (var foo:int = @app.length(); foo > @bar.length())  
>>>>>>>> 
>>>>>>>> If there are actual rules in the spec about evaluating the expression, that might apply to how we handle these expressions, otherwise I think the right thing is to resolve each expression and if the expression does not resolve to anything else, assume that it applies to the node.   I know the logic in EmitterUtils.writeE4xFilterNode isn't covering all cases.  It is trying to see what the expression resolves to, and returns false for known conditions (like a member of a class).  Just make it return false for your case (and feel free to add that case to the tests).  Eventually we'll have enough cases to either call it "good enough" or figure out a better way to determine when the expression applies to "node".
>>>>>>>> 
>>>>>>>> My 2 cents,
>>>>>>>> -Alex
>>>>>>>> 
>>>>>>>> On 8/6/18, 11:20 PM, "Harbs" <ha...@gmail.com> wrote:
>>>>>>>> 
>>>>>>>> I just looked at the spec. I think it’s correct to append “node” to the first statement of the expression only. The only exception seems to be expressions which use boolean expressions (i.e. || or &&) in which case each piece of the boolean expression should be considered a self-contained expression. So in your example, there are really two filter expressions:
>>>>>>>> 1. hasOwnProperty("@app”)
>>>>>>>> 2. @app.length() > 0
>>>>>>>> 
>>>>>>>> Both of those should have node appended to the front, but nothing else.
>>>>>>>> 
>>>>>>>> Here’s the relevant semantics in the spec (the important bit being 6a):
>>>>>>>> 
>>>>>>>>> 6. For i = 0 to list.[[Length]]-1
>>>>>>>>> a. Add list[i] to the front of the scope chain
>>>>>>>>> b. Let ref be the result of evaluating Expression using the augmented scope chain of step 6a
>>>>>>>>> c. Let match = ToBoolean(GetValue(ref))
>>>>>>>>> d. Remove list[i] from the front of the scope chain
>>>>>>>>> e. If (match == true), call the [[Append]] method of r with argument list[i]
>>>>>>>>> 7. Return r
>>>>>>>> 
>>>>>>>> Makes sense?
>>>>>>>> 
>>>>>>>> Harbs
>>>>>>>> 
>>>>>>>>> On Aug 7, 2018, at 1:39 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>>>>>>> 
>>>>>>>>> In porting Tour De Flex, there were patterns like this (explorerTree is XML):
>>>>>>>>> 
>>>>>>>>> explorerTree..node.(hasOwnProperty("@app") && @app.length() > 0)
>>>>>>>>> 
>>>>>>>>> The compiler logic before I made any changes yesterday just assumed that the first expression was a reference to the node parameter but other expressions were not, but it looks like the expression "@app.length()" was allowed in Flex as a reference to the node.  So I think the compiler has to determine what expressions evaluate to "nothing" which implies they are references to the node, and what did resolve to something.  This is all new logic and I don't know how to determine all of the test cases up front, so we'll have to keep tuning it as we find patterns that don't work as we want them to.
>>>>>>>>> 
>>>>>>>>> In your case, if the expression resolves to a VariableDefinition, that probably means that isn't a reference to node.  Not exactly sure, so you should debug into it to see what the node pattern is and return false.
>>>>>>>>> 
>>>>>>>>> Thanks,
>>>>>>>>> -Alex
>>>>>>>>> 
>>>>>>>>> On 8/6/18, 3:28 PM, "Harbs" <ha...@gmail.com> wrote:
>>>>>>>>> 
>>>>>>>>> Doesn’t it always need to be a method for it to reference the node?
>>>>>>>>> 
>>>>>>>>> I.e. child() should be node.child(), but foo.baz would not.
>>>>>>>>> 
>>>>>>>>>> On Aug 7, 2018, at 1:12 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>>>>>>>> 
>>>>>>>>>> Yep, we need more intelligent understanding of when a reference is to the node or not.
>>>>>>>>>> 
>>>>>>>>>> Debug into EmitterUtils.writeE4xFilterNode and figure out the node pattern you need.
>>>>>>>>>> 
>>>>>>>>>> -Alex
>>>>>>>>>> 
>>>>>>>>>> On 8/6/18, 3:09 PM, "Harbs" <ha...@gmail.com> wrote:
>>>>>>>>>> 
>>>>>>>>>> var folderFolders:XMLList = assetXML.folder.(child('key').indexOf(folder.key) == 0);
>>>>>>>>>> var folderImages:XMLList = assetXML.image.(child('key').indexOf(folder.key) == 0);
>>>>>>>>>> 
>>>>>>>>>> Is now compiled as:
>>>>>>>>>> 
>>>>>>>>>> var /** @type {XMLList} */ folderFolders = this.assetXML.child('folder').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
>>>>>>>>>> var /** @type {XMLList} */ folderImages = this.assetXML.child('image').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
>>>>>>>>>> 
>>>>>>>>>> “node.folder.key” is not correct. “folder” is a local variable of an un related object type.
>>>>>>>>>> 
>>>>>>>>>> I assume this broke with the recent XML filter changes.
>>>>>>>>>> 
>>>>>>>>>> Harbs
> 
> 
> 


Re: XML filters broke

Posted by Alex Harui <ah...@adobe.com.INVALID>.
Won’t know until we try it.  I'll adjust XMLList as needed.  I have an actual test case with Tour De Flex to work with.

If you have time to cherrypick IDataInput/IDataOutput for our users that would be helpful.

Thanks,
-Alex

On 8/8/18, 1:31 PM, "Harbs" <ha...@gmail.com> wrote:

    Are you sure the logic to reassign this will work here?
    
    I’m willing to rewrite the code in XMLList to use call if you think it’ll make things easier in the compiler…
    
    > On Aug 8, 2018, at 11:03 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    > 
    > 
    > 
    > On 8/8/18, 12:59 AM, "Harbs" <harbs.lists@gmail.com <ma...@gmail.com>> wrote:
    > 
    >    Does “this” in call/apply even work for a function which is not a prototype function? I thought in that case “this” is the global context.
    > 
    > From my testing, the 'this' can be re-assigned as we want it.
    > 
    >    I think 6a is kind of ambiguous. Why do you think there’s a difference between the following (other than avoiding ambiguous this references)?
    > 
    > Because there is already code that distinguishes when 'this' is supposed to be used.  So we should use it instead of crafting a whole other set of code that has a more difficult problem to solve, like whether an expression is relative to a parameter and if so, which parameter?
    > 
    > My 2 cents,
    > -Alex
    > 
    >    function() { return (over40(parseInt(this.age))) }
    >    and 
    >    function(node) { return (over40(parseInt(node.age))) }
    > 
    >    Although in fact, I think it would need to be:
    > 
    >    function(node) { return (over40(parseInt(node.child(“age”)))) }
    > 
    >> On Aug 8, 2018, at 10:33 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >> 
    >> EmitterUtils.writeThis seems to be working ok.  I think it would be better/correct to use it here.  I'm not sure if node as a parameter creates the same scope chain as node being the this pointer.  I think no, I don't think parameters are involved in lexical scoping.   IMO, 6a in the spec is saying we should make node the 'this' pointer in JS.
    >> 
    >> My 2 cents,
    >> -Alex
    >> 
    >> On 8/7/18, 10:54 AM, "Harbs" <ha...@gmail.com> wrote:
    >> 
    >>   I’m not following you. Wouldn’t we need the same logic to figure out where to insert “this”? I’m not sure what practical difference there would be between “node" and “this”, other than using apply or call. Passing in the XML node seems cleaner to me.
    >> 
    >>> On Aug 7, 2018, at 6:50 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >>> 
    >>> Yup.  After thinking about it some more, it occurs to me that we took the wrong starting point.  Right now code like:
    >>> 
    >>> over40(parseInt(age))
    >>> 
    >>> Results in:
    >>> 
    >>> function(node) { return (over40(parseInt(age))) }
    >>> 
    >>> And then the XML filter calls that function passing itself in as the node.
    >>> 
    >>> And this discussion has been about trying to figure out where to add the "node" parameter.  But now I think that 6a in the spec is really saying that the 'this' pointer should be the node.  We should transpile that filter expression like any other function body but assume it is a function run in the context of the node, like a new method on XML/XMLList, or maybe more like an anonymous function.
    >>> 
    >>> So if I'm right, then the output should be:
    >>> 
    >>> function() { return (over40(parseInt(this.age))) }
    >>> 
    >>> This is what the transpiler would have output if you had subclassed XML and added this method to it.  And then the code in XML.SWC that applies the filter has to use Function.apply/call passing the node as the 'this' pointer.
    >>> 
    >>> If we do that, then the EmitterUtils.writeE4xFilterNode would go away, and JSRoyaleEmitter.emitE4xFilter would temporarily change the model.currentClass and maybe a few other things to reference an XML object.
    >>> 
    >>> Thoughts?
    >>> -Alex
    >>> 
    >>> PS: Regarding adding tests, the filter tests have two variables.  "var a" sets up the XML, "var b" is the result of the filter.  getVariable returns the nodes for "a" then we go get child(1) which is "b" and then emit it to see what we get.
    >>> 
    >>> On 8/7/18, 3:51 AM, "Harbs" <harbs.lists@gmail.com <ma...@gmail.com>> wrote:
    >>> 
    >>>  I’m also pretty sure that the following from Mozilla’s page[1] will not work correctly:
    >>> 
    >>>  var people = <people>
    >>>    <person>
    >>>      <name>Bob</name>
    >>>      <age>32</age>
    >>>    </person>
    >>>    <person>
    >>>      <name>Joe</name>
    >>>      <age>46</age>
    >>>    </person>
    >>>  </people>;
    >>> 
    >>>  function over40(i) {
    >>>      return i > 40;
    >>>  }
    >>> 
    >>>  alert(people.person.(over40(parseInt(age))).name); // Alerts Joe
    >>> 
    >>>  https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C080f98afdf9d4bc823ed08d5fd6defd4%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693571001599413&amp;sdata=O7q%2Bzd7f1%2F8nIO64ZAGa9OcEfcaTGR0d5xj%2F7aAH6Ho%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C080f98afdf9d4bc823ed08d5fd6defd4%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693571001609423&amp;sdata=fVBJU6cb%2B5hcGWuIHVFVe8aeoZx4xLOYSmHP0bcctCI%3D&amp;reserved=0> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C080f98afdf9d4bc823ed08d5fd6defd4%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693571001609423&amp;sdata=fVBJU6cb%2B5hcGWuIHVFVe8aeoZx4xLOYSmHP0bcctCI%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C080f98afdf9d4bc823ed08d5fd6defd4%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693571001609423&amp;sdata=fVBJU6cb%2B5hcGWuIHVFVe8aeoZx4xLOYSmHP0bcctCI%3D&amp;reserved=0>> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C080f98afdf9d4bc823ed08d5fd6defd4%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693571001609423&amp;sdata=fVBJU6cb%2B5hcGWuIHVFVe8aeoZx4xLOYSmHP0bcctCI%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C080f98afdf9d4bc823ed08d5fd6defd4%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693571001609423&amp;sdata=fVBJU6cb%2B5hcGWuIHVFVe8aeoZx4xLOYSmHP0bcctCI%3D&amp;reserved=0> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C080f98afdf9d4bc823ed08d5fd6defd4%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693571001609423&amp;sdata=fVBJU6cb%2B5hcGWuIHVFVe8aeoZx4xLOYSmHP0bcctCI%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C080f98afdf9d4bc823ed08d5fd6defd4%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693571001609423&amp;sdata=fVBJU6cb%2B5hcGWuIHVFVe8aeoZx4xLOYSmHP0bcctCI%3D&amp;reserved=0>>>
    >>> 
    >>>> On Aug 7, 2018, at 1:41 PM, Harbs <ha...@gmail.com> wrote:
    >>>> 
    >>>> OK. I fixed the issue, but there’s a couple of loose ends:
    >>>> 
    >>>> 1. I don’t know how to add unit tests for these cases. In the current unit tests, I see “getNode” and “getVariable” being used. I don’t know the logic in setting up tests.
    >>>> 2. I’m not quite sure what "parentNode.getChild(0)” does. What is the parent node and will this cause my second case of e.employee.(1 == @id) to fail? Removing the check against firstChild caused the testXMLFilterWithAttribute test to fail because it prepended “node.” to “length()”.
    >>>> 
    >>>> P.S. I finally got debugging from Eclipse working on the compiler, so hopefully I’ll have a much easier time fixing compiler issues in the future. :-)
    >>>> 
    >>>> Thanks,
    >>>> Harbs
    >>>> 
    >>>>> On Aug 7, 2018, at 10:51 AM, Harbs <ha...@gmail.com> wrote:
    >>>>> 
    >>>>> Well, it looks like I was wrong.
    >>>>> 
    >>>>> I just tested the following in Flash, and then both give the same results (i.e. return the attribute):
    >>>>> 
    >>>>> var emp = e.employee.(@id == 1).@name; // name of employee with id 1
    >>>>> var foo = e.employee.(1 == @id).@name; // name of employee with id 1
    >>>>> 
    >>>>>> On Aug 7, 2018, at 10:27 AM, Harbs <ha...@gmail.com> wrote:
    >>>>>> 
    >>>>>> Your example does not seem to be right to me.
    >>>>>> 
    >>>>>> Here’s the overview of how filters are supposed to work from the spec:
    >>>>>> 
    >>>>>>> Overview
    >>>>>>> When the left operand evaluates to an XML object, the filtering predicate adds the left operand to the front of the scope chain of the current execution context, evaluates the Expression with the augmented scope chain, converts the result to a Boolean value, then restores the scope chain. If the result is true, the filtering predicate returns an XMLList containing the left operand. Otherwise it returns an empty XMLList.
    >>>>>>> When the left operand is an XMLList, the filtering predicate is applied to each XML object in the XMLList in order using the XML object as the left operand and the Expression as the right operand. It concatenates the results and returns them as a single XMLList containing all the XML properties for which the result was true. For example,
    >>>>>>> 
    >>>>>>> var john = e.employee.(name == "John"); // employees with name John
    >>>>>>> var twoemployees = e.employee.(@id == 0 || @id == 1); // employees with id's 0 & 1
    >>>>>>> var emp = e.employee.(@id == 1).name; // name of employee with id 1
    >>>>>>> 
    >>>>>>> The effect of the filtering predicate is similar to SQL’s WHERE clause or XPath’s filtering predicates.
    >>>>>>> For example, the statement:
    >>>>>>> 
    >>>>>>> // get the two employees with ids 0 and 1 using a predicate
    >>>>>>> var twoEmployees = e..employee.(@id == 0 || @id == 1);
    >>>>>>> 
    >>>>>>> produces the same result as the following set of statements:
    >>>>>>> // get the two employees with the ids 0 and 1 using a for loop
    >>>>>>> var i = 0;
    >>>>>>> var twoEmployees = new XMLList();
    >>>>>>> for each (var p in e..employee) {
    >>>>>>> with (p) {
    >>>>>>> if (@id == 0 || @id == 1) {
    >>>>>>> twoEmployees[i++] = p;
    >>>>>>> }
    >>>>>>> }
    >>>>>>> }
    >>>>>> 
    >>>>>> The question is what is "the front of the scope chain of the current execution context”? I’m pretty sure that means the start of sub-expressions. I don’t see how that can apply to the right-hand of comparison expressions. There is nothing in the spec about figuring out if a part of an expression is referring to XML or XMLList.
    >>>>>> 
    >>>>>>> On Aug 7, 2018, at 9:45 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >>>>>>> 
    >>>>>>> I don't get what portion of the spec has to do with whether we append "node" to various expressions.  IMO, the changes I made only affect 6b.  6a is handled by generating a function with "node" as the parameter (because node is list[i] in the spec).  The task in 6b is to correctly evaluate any e4x filter expression.  I'm not sure what the limits are on what you can have in a filter expression, but if you can have just plain "@app" anywhere in the filter expression, I don't believe scoping rules would know to apply that to the "node" parameter without generating the "node" before "@app".
    >>>>>>> 
    >>>>>>> There is a chance that the Flex Compiler was using "magic" to generate the "node" and really should have reported an error.  I do remember being told that the filter function can be "anything".  Even:
    >>>>>>> (var foo:int = @app.length(); foo > @bar.length())  
    >>>>>>> 
    >>>>>>> If there are actual rules in the spec about evaluating the expression, that might apply to how we handle these expressions, otherwise I think the right thing is to resolve each expression and if the expression does not resolve to anything else, assume that it applies to the node.   I know the logic in EmitterUtils.writeE4xFilterNode isn't covering all cases.  It is trying to see what the expression resolves to, and returns false for known conditions (like a member of a class).  Just make it return false for your case (and feel free to add that case to the tests).  Eventually we'll have enough cases to either call it "good enough" or figure out a better way to determine when the expression applies to "node".
    >>>>>>> 
    >>>>>>> My 2 cents,
    >>>>>>> -Alex
    >>>>>>> 
    >>>>>>> On 8/6/18, 11:20 PM, "Harbs" <ha...@gmail.com> wrote:
    >>>>>>> 
    >>>>>>> I just looked at the spec. I think it’s correct to append “node” to the first statement of the expression only. The only exception seems to be expressions which use boolean expressions (i.e. || or &&) in which case each piece of the boolean expression should be considered a self-contained expression. So in your example, there are really two filter expressions:
    >>>>>>> 1. hasOwnProperty("@app”)
    >>>>>>> 2. @app.length() > 0
    >>>>>>> 
    >>>>>>> Both of those should have node appended to the front, but nothing else.
    >>>>>>> 
    >>>>>>> Here’s the relevant semantics in the spec (the important bit being 6a):
    >>>>>>> 
    >>>>>>>> 6. For i = 0 to list.[[Length]]-1
    >>>>>>>> a. Add list[i] to the front of the scope chain
    >>>>>>>> b. Let ref be the result of evaluating Expression using the augmented scope chain of step 6a
    >>>>>>>> c. Let match = ToBoolean(GetValue(ref))
    >>>>>>>> d. Remove list[i] from the front of the scope chain
    >>>>>>>> e. If (match == true), call the [[Append]] method of r with argument list[i]
    >>>>>>>> 7. Return r
    >>>>>>> 
    >>>>>>> Makes sense?
    >>>>>>> 
    >>>>>>> Harbs
    >>>>>>> 
    >>>>>>>> On Aug 7, 2018, at 1:39 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >>>>>>>> 
    >>>>>>>> In porting Tour De Flex, there were patterns like this (explorerTree is XML):
    >>>>>>>> 
    >>>>>>>> explorerTree..node.(hasOwnProperty("@app") && @app.length() > 0)
    >>>>>>>> 
    >>>>>>>> The compiler logic before I made any changes yesterday just assumed that the first expression was a reference to the node parameter but other expressions were not, but it looks like the expression "@app.length()" was allowed in Flex as a reference to the node.  So I think the compiler has to determine what expressions evaluate to "nothing" which implies they are references to the node, and what did resolve to something.  This is all new logic and I don't know how to determine all of the test cases up front, so we'll have to keep tuning it as we find patterns that don't work as we want them to.
    >>>>>>>> 
    >>>>>>>> In your case, if the expression resolves to a VariableDefinition, that probably means that isn't a reference to node.  Not exactly sure, so you should debug into it to see what the node pattern is and return false.
    >>>>>>>> 
    >>>>>>>> Thanks,
    >>>>>>>> -Alex
    >>>>>>>> 
    >>>>>>>> On 8/6/18, 3:28 PM, "Harbs" <ha...@gmail.com> wrote:
    >>>>>>>> 
    >>>>>>>> Doesn’t it always need to be a method for it to reference the node?
    >>>>>>>> 
    >>>>>>>> I.e. child() should be node.child(), but foo.baz would not.
    >>>>>>>> 
    >>>>>>>>> On Aug 7, 2018, at 1:12 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >>>>>>>>> 
    >>>>>>>>> Yep, we need more intelligent understanding of when a reference is to the node or not.
    >>>>>>>>> 
    >>>>>>>>> Debug into EmitterUtils.writeE4xFilterNode and figure out the node pattern you need.
    >>>>>>>>> 
    >>>>>>>>> -Alex
    >>>>>>>>> 
    >>>>>>>>> On 8/6/18, 3:09 PM, "Harbs" <ha...@gmail.com> wrote:
    >>>>>>>>> 
    >>>>>>>>> var folderFolders:XMLList = assetXML.folder.(child('key').indexOf(folder.key) == 0);
    >>>>>>>>> var folderImages:XMLList = assetXML.image.(child('key').indexOf(folder.key) == 0);
    >>>>>>>>> 
    >>>>>>>>> Is now compiled as:
    >>>>>>>>> 
    >>>>>>>>> var /** @type {XMLList} */ folderFolders = this.assetXML.child('folder').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
    >>>>>>>>> var /** @type {XMLList} */ folderImages = this.assetXML.child('image').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
    >>>>>>>>> 
    >>>>>>>>> “node.folder.key” is not correct. “folder” is a local variable of an un related object type.
    >>>>>>>>> 
    >>>>>>>>> I assume this broke with the recent XML filter changes.
    >>>>>>>>> 
    >>>>>>>>> Harbs
    
    


Re: XML filters broke

Posted by Harbs <ha...@gmail.com>.
Are you sure the logic to reassign this will work here?

I’m willing to rewrite the code in XMLList to use call if you think it’ll make things easier in the compiler…

> On Aug 8, 2018, at 11:03 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
> 
> 
> 
> On 8/8/18, 12:59 AM, "Harbs" <harbs.lists@gmail.com <ma...@gmail.com>> wrote:
> 
>    Does “this” in call/apply even work for a function which is not a prototype function? I thought in that case “this” is the global context.
> 
> From my testing, the 'this' can be re-assigned as we want it.
> 
>    I think 6a is kind of ambiguous. Why do you think there’s a difference between the following (other than avoiding ambiguous this references)?
> 
> Because there is already code that distinguishes when 'this' is supposed to be used.  So we should use it instead of crafting a whole other set of code that has a more difficult problem to solve, like whether an expression is relative to a parameter and if so, which parameter?
> 
> My 2 cents,
> -Alex
> 
>    function() { return (over40(parseInt(this.age))) }
>    and 
>    function(node) { return (over40(parseInt(node.age))) }
> 
>    Although in fact, I think it would need to be:
> 
>    function(node) { return (over40(parseInt(node.child(“age”)))) }
> 
>> On Aug 8, 2018, at 10:33 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>> 
>> EmitterUtils.writeThis seems to be working ok.  I think it would be better/correct to use it here.  I'm not sure if node as a parameter creates the same scope chain as node being the this pointer.  I think no, I don't think parameters are involved in lexical scoping.   IMO, 6a in the spec is saying we should make node the 'this' pointer in JS.
>> 
>> My 2 cents,
>> -Alex
>> 
>> On 8/7/18, 10:54 AM, "Harbs" <ha...@gmail.com> wrote:
>> 
>>   I’m not following you. Wouldn’t we need the same logic to figure out where to insert “this”? I’m not sure what practical difference there would be between “node" and “this”, other than using apply or call. Passing in the XML node seems cleaner to me.
>> 
>>> On Aug 7, 2018, at 6:50 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>> 
>>> Yup.  After thinking about it some more, it occurs to me that we took the wrong starting point.  Right now code like:
>>> 
>>> over40(parseInt(age))
>>> 
>>> Results in:
>>> 
>>> function(node) { return (over40(parseInt(age))) }
>>> 
>>> And then the XML filter calls that function passing itself in as the node.
>>> 
>>> And this discussion has been about trying to figure out where to add the "node" parameter.  But now I think that 6a in the spec is really saying that the 'this' pointer should be the node.  We should transpile that filter expression like any other function body but assume it is a function run in the context of the node, like a new method on XML/XMLList, or maybe more like an anonymous function.
>>> 
>>> So if I'm right, then the output should be:
>>> 
>>> function() { return (over40(parseInt(this.age))) }
>>> 
>>> This is what the transpiler would have output if you had subclassed XML and added this method to it.  And then the code in XML.SWC that applies the filter has to use Function.apply/call passing the node as the 'this' pointer.
>>> 
>>> If we do that, then the EmitterUtils.writeE4xFilterNode would go away, and JSRoyaleEmitter.emitE4xFilter would temporarily change the model.currentClass and maybe a few other things to reference an XML object.
>>> 
>>> Thoughts?
>>> -Alex
>>> 
>>> PS: Regarding adding tests, the filter tests have two variables.  "var a" sets up the XML, "var b" is the result of the filter.  getVariable returns the nodes for "a" then we go get child(1) which is "b" and then emit it to see what we get.
>>> 
>>> On 8/7/18, 3:51 AM, "Harbs" <harbs.lists@gmail.com <ma...@gmail.com>> wrote:
>>> 
>>>  I’m also pretty sure that the following from Mozilla’s page[1] will not work correctly:
>>> 
>>>  var people = <people>
>>>    <person>
>>>      <name>Bob</name>
>>>      <age>32</age>
>>>    </person>
>>>    <person>
>>>      <name>Joe</name>
>>>      <age>46</age>
>>>    </person>
>>>  </people>;
>>> 
>>>  function over40(i) {
>>>      return i > 40;
>>>  }
>>> 
>>>  alert(people.person.(over40(parseInt(age))).name); // Alerts Joe
>>> 
>>>  https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C441a59794e0f493d1c7b08d5fd04d3f9%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693119531996112&amp;sdata=i5AMXcWmppuFIqNky5A5a3A3m9NG2x30NrzCxDw37Ss%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C441a59794e0f493d1c7b08d5fd04d3f9%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693119531996112&amp;sdata=i5AMXcWmppuFIqNky5A5a3A3m9NG2x30NrzCxDw37Ss%3D&amp;reserved=0> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C441a59794e0f493d1c7b08d5fd04d3f9%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693119531996112&amp;sdata=i5AMXcWmppuFIqNky5A5a3A3m9NG2x30NrzCxDw37Ss%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C441a59794e0f493d1c7b08d5fd04d3f9%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693119531996112&amp;sdata=i5AMXcWmppuFIqNky5A5a3A3m9NG2x30NrzCxDw37Ss%3D&amp;reserved=0>> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C441a59794e0f493d1c7b08d5fd04d3f9%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693119531996112&amp;sdata=i5AMXcWmppuFIqNky5A5a3A3m9NG2x30NrzCxDw37Ss%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C441a59794e0f493d1c7b08d5fd04d3f9%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693119531996112&amp;sdata=i5AMXcWmppuFIqNky5A5a3A3m9NG2x30NrzCxDw37Ss%3D&amp;reserved=0> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C441a59794e0f493d1c7b08d5fd04d3f9%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693119531996112&amp;sdata=i5AMXcWmppuFIqNky5A5a3A3m9NG2x30NrzCxDw37Ss%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C441a59794e0f493d1c7b08d5fd04d3f9%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693119531996112&amp;sdata=i5AMXcWmppuFIqNky5A5a3A3m9NG2x30NrzCxDw37Ss%3D&amp;reserved=0>>>
>>> 
>>>> On Aug 7, 2018, at 1:41 PM, Harbs <ha...@gmail.com> wrote:
>>>> 
>>>> OK. I fixed the issue, but there’s a couple of loose ends:
>>>> 
>>>> 1. I don’t know how to add unit tests for these cases. In the current unit tests, I see “getNode” and “getVariable” being used. I don’t know the logic in setting up tests.
>>>> 2. I’m not quite sure what "parentNode.getChild(0)” does. What is the parent node and will this cause my second case of e.employee.(1 == @id) to fail? Removing the check against firstChild caused the testXMLFilterWithAttribute test to fail because it prepended “node.” to “length()”.
>>>> 
>>>> P.S. I finally got debugging from Eclipse working on the compiler, so hopefully I’ll have a much easier time fixing compiler issues in the future. :-)
>>>> 
>>>> Thanks,
>>>> Harbs
>>>> 
>>>>> On Aug 7, 2018, at 10:51 AM, Harbs <ha...@gmail.com> wrote:
>>>>> 
>>>>> Well, it looks like I was wrong.
>>>>> 
>>>>> I just tested the following in Flash, and then both give the same results (i.e. return the attribute):
>>>>> 
>>>>> var emp = e.employee.(@id == 1).@name; // name of employee with id 1
>>>>> var foo = e.employee.(1 == @id).@name; // name of employee with id 1
>>>>> 
>>>>>> On Aug 7, 2018, at 10:27 AM, Harbs <ha...@gmail.com> wrote:
>>>>>> 
>>>>>> Your example does not seem to be right to me.
>>>>>> 
>>>>>> Here’s the overview of how filters are supposed to work from the spec:
>>>>>> 
>>>>>>> Overview
>>>>>>> When the left operand evaluates to an XML object, the filtering predicate adds the left operand to the front of the scope chain of the current execution context, evaluates the Expression with the augmented scope chain, converts the result to a Boolean value, then restores the scope chain. If the result is true, the filtering predicate returns an XMLList containing the left operand. Otherwise it returns an empty XMLList.
>>>>>>> When the left operand is an XMLList, the filtering predicate is applied to each XML object in the XMLList in order using the XML object as the left operand and the Expression as the right operand. It concatenates the results and returns them as a single XMLList containing all the XML properties for which the result was true. For example,
>>>>>>> 
>>>>>>> var john = e.employee.(name == "John"); // employees with name John
>>>>>>> var twoemployees = e.employee.(@id == 0 || @id == 1); // employees with id's 0 & 1
>>>>>>> var emp = e.employee.(@id == 1).name; // name of employee with id 1
>>>>>>> 
>>>>>>> The effect of the filtering predicate is similar to SQL’s WHERE clause or XPath’s filtering predicates.
>>>>>>> For example, the statement:
>>>>>>> 
>>>>>>> // get the two employees with ids 0 and 1 using a predicate
>>>>>>> var twoEmployees = e..employee.(@id == 0 || @id == 1);
>>>>>>> 
>>>>>>> produces the same result as the following set of statements:
>>>>>>> // get the two employees with the ids 0 and 1 using a for loop
>>>>>>> var i = 0;
>>>>>>> var twoEmployees = new XMLList();
>>>>>>> for each (var p in e..employee) {
>>>>>>> with (p) {
>>>>>>> if (@id == 0 || @id == 1) {
>>>>>>> twoEmployees[i++] = p;
>>>>>>> }
>>>>>>> }
>>>>>>> }
>>>>>> 
>>>>>> The question is what is "the front of the scope chain of the current execution context”? I’m pretty sure that means the start of sub-expressions. I don’t see how that can apply to the right-hand of comparison expressions. There is nothing in the spec about figuring out if a part of an expression is referring to XML or XMLList.
>>>>>> 
>>>>>>> On Aug 7, 2018, at 9:45 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>>>>> 
>>>>>>> I don't get what portion of the spec has to do with whether we append "node" to various expressions.  IMO, the changes I made only affect 6b.  6a is handled by generating a function with "node" as the parameter (because node is list[i] in the spec).  The task in 6b is to correctly evaluate any e4x filter expression.  I'm not sure what the limits are on what you can have in a filter expression, but if you can have just plain "@app" anywhere in the filter expression, I don't believe scoping rules would know to apply that to the "node" parameter without generating the "node" before "@app".
>>>>>>> 
>>>>>>> There is a chance that the Flex Compiler was using "magic" to generate the "node" and really should have reported an error.  I do remember being told that the filter function can be "anything".  Even:
>>>>>>> (var foo:int = @app.length(); foo > @bar.length())  
>>>>>>> 
>>>>>>> If there are actual rules in the spec about evaluating the expression, that might apply to how we handle these expressions, otherwise I think the right thing is to resolve each expression and if the expression does not resolve to anything else, assume that it applies to the node.   I know the logic in EmitterUtils.writeE4xFilterNode isn't covering all cases.  It is trying to see what the expression resolves to, and returns false for known conditions (like a member of a class).  Just make it return false for your case (and feel free to add that case to the tests).  Eventually we'll have enough cases to either call it "good enough" or figure out a better way to determine when the expression applies to "node".
>>>>>>> 
>>>>>>> My 2 cents,
>>>>>>> -Alex
>>>>>>> 
>>>>>>> On 8/6/18, 11:20 PM, "Harbs" <ha...@gmail.com> wrote:
>>>>>>> 
>>>>>>> I just looked at the spec. I think it’s correct to append “node” to the first statement of the expression only. The only exception seems to be expressions which use boolean expressions (i.e. || or &&) in which case each piece of the boolean expression should be considered a self-contained expression. So in your example, there are really two filter expressions:
>>>>>>> 1. hasOwnProperty("@app”)
>>>>>>> 2. @app.length() > 0
>>>>>>> 
>>>>>>> Both of those should have node appended to the front, but nothing else.
>>>>>>> 
>>>>>>> Here’s the relevant semantics in the spec (the important bit being 6a):
>>>>>>> 
>>>>>>>> 6. For i = 0 to list.[[Length]]-1
>>>>>>>> a. Add list[i] to the front of the scope chain
>>>>>>>> b. Let ref be the result of evaluating Expression using the augmented scope chain of step 6a
>>>>>>>> c. Let match = ToBoolean(GetValue(ref))
>>>>>>>> d. Remove list[i] from the front of the scope chain
>>>>>>>> e. If (match == true), call the [[Append]] method of r with argument list[i]
>>>>>>>> 7. Return r
>>>>>>> 
>>>>>>> Makes sense?
>>>>>>> 
>>>>>>> Harbs
>>>>>>> 
>>>>>>>> On Aug 7, 2018, at 1:39 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>>>>>> 
>>>>>>>> In porting Tour De Flex, there were patterns like this (explorerTree is XML):
>>>>>>>> 
>>>>>>>> explorerTree..node.(hasOwnProperty("@app") && @app.length() > 0)
>>>>>>>> 
>>>>>>>> The compiler logic before I made any changes yesterday just assumed that the first expression was a reference to the node parameter but other expressions were not, but it looks like the expression "@app.length()" was allowed in Flex as a reference to the node.  So I think the compiler has to determine what expressions evaluate to "nothing" which implies they are references to the node, and what did resolve to something.  This is all new logic and I don't know how to determine all of the test cases up front, so we'll have to keep tuning it as we find patterns that don't work as we want them to.
>>>>>>>> 
>>>>>>>> In your case, if the expression resolves to a VariableDefinition, that probably means that isn't a reference to node.  Not exactly sure, so you should debug into it to see what the node pattern is and return false.
>>>>>>>> 
>>>>>>>> Thanks,
>>>>>>>> -Alex
>>>>>>>> 
>>>>>>>> On 8/6/18, 3:28 PM, "Harbs" <ha...@gmail.com> wrote:
>>>>>>>> 
>>>>>>>> Doesn’t it always need to be a method for it to reference the node?
>>>>>>>> 
>>>>>>>> I.e. child() should be node.child(), but foo.baz would not.
>>>>>>>> 
>>>>>>>>> On Aug 7, 2018, at 1:12 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>>>>>>> 
>>>>>>>>> Yep, we need more intelligent understanding of when a reference is to the node or not.
>>>>>>>>> 
>>>>>>>>> Debug into EmitterUtils.writeE4xFilterNode and figure out the node pattern you need.
>>>>>>>>> 
>>>>>>>>> -Alex
>>>>>>>>> 
>>>>>>>>> On 8/6/18, 3:09 PM, "Harbs" <ha...@gmail.com> wrote:
>>>>>>>>> 
>>>>>>>>> var folderFolders:XMLList = assetXML.folder.(child('key').indexOf(folder.key) == 0);
>>>>>>>>> var folderImages:XMLList = assetXML.image.(child('key').indexOf(folder.key) == 0);
>>>>>>>>> 
>>>>>>>>> Is now compiled as:
>>>>>>>>> 
>>>>>>>>> var /** @type {XMLList} */ folderFolders = this.assetXML.child('folder').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
>>>>>>>>> var /** @type {XMLList} */ folderImages = this.assetXML.child('image').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
>>>>>>>>> 
>>>>>>>>> “node.folder.key” is not correct. “folder” is a local variable of an un related object type.
>>>>>>>>> 
>>>>>>>>> I assume this broke with the recent XML filter changes.
>>>>>>>>> 
>>>>>>>>> Harbs


Re: XML filters broke

Posted by Alex Harui <ah...@adobe.com.INVALID>.

On 8/8/18, 12:59 AM, "Harbs" <ha...@gmail.com> wrote:

    Does “this” in call/apply even work for a function which is not a prototype function? I thought in that case “this” is the global context.

From my testing, the 'this' can be re-assigned as we want it.
    
    I think 6a is kind of ambiguous. Why do you think there’s a difference between the following (other than avoiding ambiguous this references)?
    
Because there is already code that distinguishes when 'this' is supposed to be used.  So we should use it instead of crafting a whole other set of code that has a more difficult problem to solve, like whether an expression is relative to a parameter and if so, which parameter?

My 2 cents,
-Alex

    function() { return (over40(parseInt(this.age))) }
    and 
    function(node) { return (over40(parseInt(node.age))) }
    
    Although in fact, I think it would need to be:
    
    function(node) { return (over40(parseInt(node.child(“age”)))) }
    
    > On Aug 8, 2018, at 10:33 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    > 
    > EmitterUtils.writeThis seems to be working ok.  I think it would be better/correct to use it here.  I'm not sure if node as a parameter creates the same scope chain as node being the this pointer.  I think no, I don't think parameters are involved in lexical scoping.   IMO, 6a in the spec is saying we should make node the 'this' pointer in JS.
    > 
    > My 2 cents,
    > -Alex
    > 
    > On 8/7/18, 10:54 AM, "Harbs" <ha...@gmail.com> wrote:
    > 
    >    I’m not following you. Wouldn’t we need the same logic to figure out where to insert “this”? I’m not sure what practical difference there would be between “node" and “this”, other than using apply or call. Passing in the XML node seems cleaner to me.
    > 
    >> On Aug 7, 2018, at 6:50 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >> 
    >> Yup.  After thinking about it some more, it occurs to me that we took the wrong starting point.  Right now code like:
    >> 
    >> over40(parseInt(age))
    >> 
    >> Results in:
    >> 
    >> function(node) { return (over40(parseInt(age))) }
    >> 
    >> And then the XML filter calls that function passing itself in as the node.
    >> 
    >> And this discussion has been about trying to figure out where to add the "node" parameter.  But now I think that 6a in the spec is really saying that the 'this' pointer should be the node.  We should transpile that filter expression like any other function body but assume it is a function run in the context of the node, like a new method on XML/XMLList, or maybe more like an anonymous function.
    >> 
    >> So if I'm right, then the output should be:
    >> 
    >> function() { return (over40(parseInt(this.age))) }
    >> 
    >> This is what the transpiler would have output if you had subclassed XML and added this method to it.  And then the code in XML.SWC that applies the filter has to use Function.apply/call passing the node as the 'this' pointer.
    >> 
    >> If we do that, then the EmitterUtils.writeE4xFilterNode would go away, and JSRoyaleEmitter.emitE4xFilter would temporarily change the model.currentClass and maybe a few other things to reference an XML object.
    >> 
    >> Thoughts?
    >> -Alex
    >> 
    >> PS: Regarding adding tests, the filter tests have two variables.  "var a" sets up the XML, "var b" is the result of the filter.  getVariable returns the nodes for "a" then we go get child(1) which is "b" and then emit it to see what we get.
    >> 
    >> On 8/7/18, 3:51 AM, "Harbs" <harbs.lists@gmail.com <ma...@gmail.com>> wrote:
    >> 
    >>   I’m also pretty sure that the following from Mozilla’s page[1] will not work correctly:
    >> 
    >>   var people = <people>
    >>     <person>
    >>       <name>Bob</name>
    >>       <age>32</age>
    >>     </person>
    >>     <person>
    >>       <name>Joe</name>
    >>       <age>46</age>
    >>     </person>
    >>   </people>;
    >> 
    >>   function over40(i) {
    >>       return i > 40;
    >>   }
    >> 
    >>   alert(people.person.(over40(parseInt(age))).name); // Alerts Joe
    >> 
    >>   https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C441a59794e0f493d1c7b08d5fd04d3f9%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693119531996112&amp;sdata=i5AMXcWmppuFIqNky5A5a3A3m9NG2x30NrzCxDw37Ss%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C441a59794e0f493d1c7b08d5fd04d3f9%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693119531996112&amp;sdata=i5AMXcWmppuFIqNky5A5a3A3m9NG2x30NrzCxDw37Ss%3D&amp;reserved=0> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C441a59794e0f493d1c7b08d5fd04d3f9%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693119531996112&amp;sdata=i5AMXcWmppuFIqNky5A5a3A3m9NG2x30NrzCxDw37Ss%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C441a59794e0f493d1c7b08d5fd04d3f9%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636693119531996112&amp;sdata=i5AMXcWmppuFIqNky5A5a3A3m9NG2x30NrzCxDw37Ss%3D&amp;reserved=0>>
    >> 
    >>> On Aug 7, 2018, at 1:41 PM, Harbs <ha...@gmail.com> wrote:
    >>> 
    >>> OK. I fixed the issue, but there’s a couple of loose ends:
    >>> 
    >>> 1. I don’t know how to add unit tests for these cases. In the current unit tests, I see “getNode” and “getVariable” being used. I don’t know the logic in setting up tests.
    >>> 2. I’m not quite sure what "parentNode.getChild(0)” does. What is the parent node and will this cause my second case of e.employee.(1 == @id) to fail? Removing the check against firstChild caused the testXMLFilterWithAttribute test to fail because it prepended “node.” to “length()”.
    >>> 
    >>> P.S. I finally got debugging from Eclipse working on the compiler, so hopefully I’ll have a much easier time fixing compiler issues in the future. :-)
    >>> 
    >>> Thanks,
    >>> Harbs
    >>> 
    >>>> On Aug 7, 2018, at 10:51 AM, Harbs <ha...@gmail.com> wrote:
    >>>> 
    >>>> Well, it looks like I was wrong.
    >>>> 
    >>>> I just tested the following in Flash, and then both give the same results (i.e. return the attribute):
    >>>> 
    >>>> var emp = e.employee.(@id == 1).@name; // name of employee with id 1
    >>>> var foo = e.employee.(1 == @id).@name; // name of employee with id 1
    >>>> 
    >>>>> On Aug 7, 2018, at 10:27 AM, Harbs <ha...@gmail.com> wrote:
    >>>>> 
    >>>>> Your example does not seem to be right to me.
    >>>>> 
    >>>>> Here’s the overview of how filters are supposed to work from the spec:
    >>>>> 
    >>>>>> Overview
    >>>>>> When the left operand evaluates to an XML object, the filtering predicate adds the left operand to the front of the scope chain of the current execution context, evaluates the Expression with the augmented scope chain, converts the result to a Boolean value, then restores the scope chain. If the result is true, the filtering predicate returns an XMLList containing the left operand. Otherwise it returns an empty XMLList.
    >>>>>> When the left operand is an XMLList, the filtering predicate is applied to each XML object in the XMLList in order using the XML object as the left operand and the Expression as the right operand. It concatenates the results and returns them as a single XMLList containing all the XML properties for which the result was true. For example,
    >>>>>> 
    >>>>>> var john = e.employee.(name == "John"); // employees with name John
    >>>>>> var twoemployees = e.employee.(@id == 0 || @id == 1); // employees with id's 0 & 1
    >>>>>> var emp = e.employee.(@id == 1).name; // name of employee with id 1
    >>>>>> 
    >>>>>> The effect of the filtering predicate is similar to SQL’s WHERE clause or XPath’s filtering predicates.
    >>>>>> For example, the statement:
    >>>>>> 
    >>>>>> // get the two employees with ids 0 and 1 using a predicate
    >>>>>> var twoEmployees = e..employee.(@id == 0 || @id == 1);
    >>>>>> 
    >>>>>> produces the same result as the following set of statements:
    >>>>>> // get the two employees with the ids 0 and 1 using a for loop
    >>>>>> var i = 0;
    >>>>>> var twoEmployees = new XMLList();
    >>>>>> for each (var p in e..employee) {
    >>>>>> with (p) {
    >>>>>> if (@id == 0 || @id == 1) {
    >>>>>>  twoEmployees[i++] = p;
    >>>>>> }
    >>>>>> }
    >>>>>> }
    >>>>> 
    >>>>> The question is what is "the front of the scope chain of the current execution context”? I’m pretty sure that means the start of sub-expressions. I don’t see how that can apply to the right-hand of comparison expressions. There is nothing in the spec about figuring out if a part of an expression is referring to XML or XMLList.
    >>>>> 
    >>>>>> On Aug 7, 2018, at 9:45 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >>>>>> 
    >>>>>> I don't get what portion of the spec has to do with whether we append "node" to various expressions.  IMO, the changes I made only affect 6b.  6a is handled by generating a function with "node" as the parameter (because node is list[i] in the spec).  The task in 6b is to correctly evaluate any e4x filter expression.  I'm not sure what the limits are on what you can have in a filter expression, but if you can have just plain "@app" anywhere in the filter expression, I don't believe scoping rules would know to apply that to the "node" parameter without generating the "node" before "@app".
    >>>>>> 
    >>>>>> There is a chance that the Flex Compiler was using "magic" to generate the "node" and really should have reported an error.  I do remember being told that the filter function can be "anything".  Even:
    >>>>>> (var foo:int = @app.length(); foo > @bar.length())  
    >>>>>> 
    >>>>>> If there are actual rules in the spec about evaluating the expression, that might apply to how we handle these expressions, otherwise I think the right thing is to resolve each expression and if the expression does not resolve to anything else, assume that it applies to the node.   I know the logic in EmitterUtils.writeE4xFilterNode isn't covering all cases.  It is trying to see what the expression resolves to, and returns false for known conditions (like a member of a class).  Just make it return false for your case (and feel free to add that case to the tests).  Eventually we'll have enough cases to either call it "good enough" or figure out a better way to determine when the expression applies to "node".
    >>>>>> 
    >>>>>> My 2 cents,
    >>>>>> -Alex
    >>>>>> 
    >>>>>> On 8/6/18, 11:20 PM, "Harbs" <ha...@gmail.com> wrote:
    >>>>>> 
    >>>>>> I just looked at the spec. I think it’s correct to append “node” to the first statement of the expression only. The only exception seems to be expressions which use boolean expressions (i.e. || or &&) in which case each piece of the boolean expression should be considered a self-contained expression. So in your example, there are really two filter expressions:
    >>>>>> 1. hasOwnProperty("@app”)
    >>>>>> 2. @app.length() > 0
    >>>>>> 
    >>>>>> Both of those should have node appended to the front, but nothing else.
    >>>>>> 
    >>>>>> Here’s the relevant semantics in the spec (the important bit being 6a):
    >>>>>> 
    >>>>>>> 6. For i = 0 to list.[[Length]]-1
    >>>>>>> a. Add list[i] to the front of the scope chain
    >>>>>>> b. Let ref be the result of evaluating Expression using the augmented scope chain of step 6a
    >>>>>>> c. Let match = ToBoolean(GetValue(ref))
    >>>>>>> d. Remove list[i] from the front of the scope chain
    >>>>>>> e. If (match == true), call the [[Append]] method of r with argument list[i]
    >>>>>>> 7. Return r
    >>>>>> 
    >>>>>> Makes sense?
    >>>>>> 
    >>>>>> Harbs
    >>>>>> 
    >>>>>>> On Aug 7, 2018, at 1:39 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >>>>>>> 
    >>>>>>> In porting Tour De Flex, there were patterns like this (explorerTree is XML):
    >>>>>>> 
    >>>>>>> explorerTree..node.(hasOwnProperty("@app") && @app.length() > 0)
    >>>>>>> 
    >>>>>>> The compiler logic before I made any changes yesterday just assumed that the first expression was a reference to the node parameter but other expressions were not, but it looks like the expression "@app.length()" was allowed in Flex as a reference to the node.  So I think the compiler has to determine what expressions evaluate to "nothing" which implies they are references to the node, and what did resolve to something.  This is all new logic and I don't know how to determine all of the test cases up front, so we'll have to keep tuning it as we find patterns that don't work as we want them to.
    >>>>>>> 
    >>>>>>> In your case, if the expression resolves to a VariableDefinition, that probably means that isn't a reference to node.  Not exactly sure, so you should debug into it to see what the node pattern is and return false.
    >>>>>>> 
    >>>>>>> Thanks,
    >>>>>>> -Alex
    >>>>>>> 
    >>>>>>> On 8/6/18, 3:28 PM, "Harbs" <ha...@gmail.com> wrote:
    >>>>>>> 
    >>>>>>> Doesn’t it always need to be a method for it to reference the node?
    >>>>>>> 
    >>>>>>> I.e. child() should be node.child(), but foo.baz would not.
    >>>>>>> 
    >>>>>>>> On Aug 7, 2018, at 1:12 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >>>>>>>> 
    >>>>>>>> Yep, we need more intelligent understanding of when a reference is to the node or not.
    >>>>>>>> 
    >>>>>>>> Debug into EmitterUtils.writeE4xFilterNode and figure out the node pattern you need.
    >>>>>>>> 
    >>>>>>>> -Alex
    >>>>>>>> 
    >>>>>>>> On 8/6/18, 3:09 PM, "Harbs" <ha...@gmail.com> wrote:
    >>>>>>>> 
    >>>>>>>> var folderFolders:XMLList = assetXML.folder.(child('key').indexOf(folder.key) == 0);
    >>>>>>>> var folderImages:XMLList = assetXML.image.(child('key').indexOf(folder.key) == 0);
    >>>>>>>> 
    >>>>>>>> Is now compiled as:
    >>>>>>>> 
    >>>>>>>> var /** @type {XMLList} */ folderFolders = this.assetXML.child('folder').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
    >>>>>>>> var /** @type {XMLList} */ folderImages = this.assetXML.child('image').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
    >>>>>>>> 
    >>>>>>>> “node.folder.key” is not correct. “folder” is a local variable of an un related object type.
    >>>>>>>> 
    >>>>>>>> I assume this broke with the recent XML filter changes.
    >>>>>>>> 
    >>>>>>>> Harbs
    > 
    > 
    > 
    
    


Re: XML filters broke

Posted by Harbs <ha...@gmail.com>.
Does “this” in call/apply even work for a function which is not a prototype function? I thought in that case “this” is the global context.

I think 6a is kind of ambiguous. Why do you think there’s a difference between the following (other than avoiding ambiguous this references)?

function() { return (over40(parseInt(this.age))) }
and 
function(node) { return (over40(parseInt(node.age))) }

Although in fact, I think it would need to be:

function(node) { return (over40(parseInt(node.child(“age”)))) }

> On Aug 8, 2018, at 10:33 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
> 
> EmitterUtils.writeThis seems to be working ok.  I think it would be better/correct to use it here.  I'm not sure if node as a parameter creates the same scope chain as node being the this pointer.  I think no, I don't think parameters are involved in lexical scoping.   IMO, 6a in the spec is saying we should make node the 'this' pointer in JS.
> 
> My 2 cents,
> -Alex
> 
> On 8/7/18, 10:54 AM, "Harbs" <ha...@gmail.com> wrote:
> 
>    I’m not following you. Wouldn’t we need the same logic to figure out where to insert “this”? I’m not sure what practical difference there would be between “node" and “this”, other than using apply or call. Passing in the XML node seems cleaner to me.
> 
>> On Aug 7, 2018, at 6:50 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>> 
>> Yup.  After thinking about it some more, it occurs to me that we took the wrong starting point.  Right now code like:
>> 
>> over40(parseInt(age))
>> 
>> Results in:
>> 
>> function(node) { return (over40(parseInt(age))) }
>> 
>> And then the XML filter calls that function passing itself in as the node.
>> 
>> And this discussion has been about trying to figure out where to add the "node" parameter.  But now I think that 6a in the spec is really saying that the 'this' pointer should be the node.  We should transpile that filter expression like any other function body but assume it is a function run in the context of the node, like a new method on XML/XMLList, or maybe more like an anonymous function.
>> 
>> So if I'm right, then the output should be:
>> 
>> function() { return (over40(parseInt(this.age))) }
>> 
>> This is what the transpiler would have output if you had subclassed XML and added this method to it.  And then the code in XML.SWC that applies the filter has to use Function.apply/call passing the node as the 'this' pointer.
>> 
>> If we do that, then the EmitterUtils.writeE4xFilterNode would go away, and JSRoyaleEmitter.emitE4xFilter would temporarily change the model.currentClass and maybe a few other things to reference an XML object.
>> 
>> Thoughts?
>> -Alex
>> 
>> PS: Regarding adding tests, the filter tests have two variables.  "var a" sets up the XML, "var b" is the result of the filter.  getVariable returns the nodes for "a" then we go get child(1) which is "b" and then emit it to see what we get.
>> 
>> On 8/7/18, 3:51 AM, "Harbs" <harbs.lists@gmail.com <ma...@gmail.com>> wrote:
>> 
>>   I’m also pretty sure that the following from Mozilla’s page[1] will not work correctly:
>> 
>>   var people = <people>
>>     <person>
>>       <name>Bob</name>
>>       <age>32</age>
>>     </person>
>>     <person>
>>       <name>Joe</name>
>>       <age>46</age>
>>     </person>
>>   </people>;
>> 
>>   function over40(i) {
>>       return i > 40;
>>   }
>> 
>>   alert(people.person.(over40(parseInt(age))).name); // Alerts Joe
>> 
>>   https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C47aa707c6e664beeafe308d5fc53afbd%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636692358717325505&amp;sdata=I1dJz1%2BApUMPtSZNoFFWF68u1IeygB6fiIF%2FKM9zq4Y%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C47aa707c6e664beeafe308d5fc53afbd%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636692358717325505&amp;sdata=I1dJz1%2BApUMPtSZNoFFWF68u1IeygB6fiIF%2FKM9zq4Y%3D&amp;reserved=0> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C47aa707c6e664beeafe308d5fc53afbd%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636692358717325505&amp;sdata=I1dJz1%2BApUMPtSZNoFFWF68u1IeygB6fiIF%2FKM9zq4Y%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C47aa707c6e664beeafe308d5fc53afbd%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636692358717325505&amp;sdata=I1dJz1%2BApUMPtSZNoFFWF68u1IeygB6fiIF%2FKM9zq4Y%3D&amp;reserved=0>>
>> 
>>> On Aug 7, 2018, at 1:41 PM, Harbs <ha...@gmail.com> wrote:
>>> 
>>> OK. I fixed the issue, but there’s a couple of loose ends:
>>> 
>>> 1. I don’t know how to add unit tests for these cases. In the current unit tests, I see “getNode” and “getVariable” being used. I don’t know the logic in setting up tests.
>>> 2. I’m not quite sure what "parentNode.getChild(0)” does. What is the parent node and will this cause my second case of e.employee.(1 == @id) to fail? Removing the check against firstChild caused the testXMLFilterWithAttribute test to fail because it prepended “node.” to “length()”.
>>> 
>>> P.S. I finally got debugging from Eclipse working on the compiler, so hopefully I’ll have a much easier time fixing compiler issues in the future. :-)
>>> 
>>> Thanks,
>>> Harbs
>>> 
>>>> On Aug 7, 2018, at 10:51 AM, Harbs <ha...@gmail.com> wrote:
>>>> 
>>>> Well, it looks like I was wrong.
>>>> 
>>>> I just tested the following in Flash, and then both give the same results (i.e. return the attribute):
>>>> 
>>>> var emp = e.employee.(@id == 1).@name; // name of employee with id 1
>>>> var foo = e.employee.(1 == @id).@name; // name of employee with id 1
>>>> 
>>>>> On Aug 7, 2018, at 10:27 AM, Harbs <ha...@gmail.com> wrote:
>>>>> 
>>>>> Your example does not seem to be right to me.
>>>>> 
>>>>> Here’s the overview of how filters are supposed to work from the spec:
>>>>> 
>>>>>> Overview
>>>>>> When the left operand evaluates to an XML object, the filtering predicate adds the left operand to the front of the scope chain of the current execution context, evaluates the Expression with the augmented scope chain, converts the result to a Boolean value, then restores the scope chain. If the result is true, the filtering predicate returns an XMLList containing the left operand. Otherwise it returns an empty XMLList.
>>>>>> When the left operand is an XMLList, the filtering predicate is applied to each XML object in the XMLList in order using the XML object as the left operand and the Expression as the right operand. It concatenates the results and returns them as a single XMLList containing all the XML properties for which the result was true. For example,
>>>>>> 
>>>>>> var john = e.employee.(name == "John"); // employees with name John
>>>>>> var twoemployees = e.employee.(@id == 0 || @id == 1); // employees with id's 0 & 1
>>>>>> var emp = e.employee.(@id == 1).name; // name of employee with id 1
>>>>>> 
>>>>>> The effect of the filtering predicate is similar to SQL’s WHERE clause or XPath’s filtering predicates.
>>>>>> For example, the statement:
>>>>>> 
>>>>>> // get the two employees with ids 0 and 1 using a predicate
>>>>>> var twoEmployees = e..employee.(@id == 0 || @id == 1);
>>>>>> 
>>>>>> produces the same result as the following set of statements:
>>>>>> // get the two employees with the ids 0 and 1 using a for loop
>>>>>> var i = 0;
>>>>>> var twoEmployees = new XMLList();
>>>>>> for each (var p in e..employee) {
>>>>>> with (p) {
>>>>>> if (@id == 0 || @id == 1) {
>>>>>>  twoEmployees[i++] = p;
>>>>>> }
>>>>>> }
>>>>>> }
>>>>> 
>>>>> The question is what is "the front of the scope chain of the current execution context”? I’m pretty sure that means the start of sub-expressions. I don’t see how that can apply to the right-hand of comparison expressions. There is nothing in the spec about figuring out if a part of an expression is referring to XML or XMLList.
>>>>> 
>>>>>> On Aug 7, 2018, at 9:45 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>>>> 
>>>>>> I don't get what portion of the spec has to do with whether we append "node" to various expressions.  IMO, the changes I made only affect 6b.  6a is handled by generating a function with "node" as the parameter (because node is list[i] in the spec).  The task in 6b is to correctly evaluate any e4x filter expression.  I'm not sure what the limits are on what you can have in a filter expression, but if you can have just plain "@app" anywhere in the filter expression, I don't believe scoping rules would know to apply that to the "node" parameter without generating the "node" before "@app".
>>>>>> 
>>>>>> There is a chance that the Flex Compiler was using "magic" to generate the "node" and really should have reported an error.  I do remember being told that the filter function can be "anything".  Even:
>>>>>> (var foo:int = @app.length(); foo > @bar.length())  
>>>>>> 
>>>>>> If there are actual rules in the spec about evaluating the expression, that might apply to how we handle these expressions, otherwise I think the right thing is to resolve each expression and if the expression does not resolve to anything else, assume that it applies to the node.   I know the logic in EmitterUtils.writeE4xFilterNode isn't covering all cases.  It is trying to see what the expression resolves to, and returns false for known conditions (like a member of a class).  Just make it return false for your case (and feel free to add that case to the tests).  Eventually we'll have enough cases to either call it "good enough" or figure out a better way to determine when the expression applies to "node".
>>>>>> 
>>>>>> My 2 cents,
>>>>>> -Alex
>>>>>> 
>>>>>> On 8/6/18, 11:20 PM, "Harbs" <ha...@gmail.com> wrote:
>>>>>> 
>>>>>> I just looked at the spec. I think it’s correct to append “node” to the first statement of the expression only. The only exception seems to be expressions which use boolean expressions (i.e. || or &&) in which case each piece of the boolean expression should be considered a self-contained expression. So in your example, there are really two filter expressions:
>>>>>> 1. hasOwnProperty("@app”)
>>>>>> 2. @app.length() > 0
>>>>>> 
>>>>>> Both of those should have node appended to the front, but nothing else.
>>>>>> 
>>>>>> Here’s the relevant semantics in the spec (the important bit being 6a):
>>>>>> 
>>>>>>> 6. For i = 0 to list.[[Length]]-1
>>>>>>> a. Add list[i] to the front of the scope chain
>>>>>>> b. Let ref be the result of evaluating Expression using the augmented scope chain of step 6a
>>>>>>> c. Let match = ToBoolean(GetValue(ref))
>>>>>>> d. Remove list[i] from the front of the scope chain
>>>>>>> e. If (match == true), call the [[Append]] method of r with argument list[i]
>>>>>>> 7. Return r
>>>>>> 
>>>>>> Makes sense?
>>>>>> 
>>>>>> Harbs
>>>>>> 
>>>>>>> On Aug 7, 2018, at 1:39 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>>>>> 
>>>>>>> In porting Tour De Flex, there were patterns like this (explorerTree is XML):
>>>>>>> 
>>>>>>> explorerTree..node.(hasOwnProperty("@app") && @app.length() > 0)
>>>>>>> 
>>>>>>> The compiler logic before I made any changes yesterday just assumed that the first expression was a reference to the node parameter but other expressions were not, but it looks like the expression "@app.length()" was allowed in Flex as a reference to the node.  So I think the compiler has to determine what expressions evaluate to "nothing" which implies they are references to the node, and what did resolve to something.  This is all new logic and I don't know how to determine all of the test cases up front, so we'll have to keep tuning it as we find patterns that don't work as we want them to.
>>>>>>> 
>>>>>>> In your case, if the expression resolves to a VariableDefinition, that probably means that isn't a reference to node.  Not exactly sure, so you should debug into it to see what the node pattern is and return false.
>>>>>>> 
>>>>>>> Thanks,
>>>>>>> -Alex
>>>>>>> 
>>>>>>> On 8/6/18, 3:28 PM, "Harbs" <ha...@gmail.com> wrote:
>>>>>>> 
>>>>>>> Doesn’t it always need to be a method for it to reference the node?
>>>>>>> 
>>>>>>> I.e. child() should be node.child(), but foo.baz would not.
>>>>>>> 
>>>>>>>> On Aug 7, 2018, at 1:12 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>>>>>> 
>>>>>>>> Yep, we need more intelligent understanding of when a reference is to the node or not.
>>>>>>>> 
>>>>>>>> Debug into EmitterUtils.writeE4xFilterNode and figure out the node pattern you need.
>>>>>>>> 
>>>>>>>> -Alex
>>>>>>>> 
>>>>>>>> On 8/6/18, 3:09 PM, "Harbs" <ha...@gmail.com> wrote:
>>>>>>>> 
>>>>>>>> var folderFolders:XMLList = assetXML.folder.(child('key').indexOf(folder.key) == 0);
>>>>>>>> var folderImages:XMLList = assetXML.image.(child('key').indexOf(folder.key) == 0);
>>>>>>>> 
>>>>>>>> Is now compiled as:
>>>>>>>> 
>>>>>>>> var /** @type {XMLList} */ folderFolders = this.assetXML.child('folder').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
>>>>>>>> var /** @type {XMLList} */ folderImages = this.assetXML.child('image').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
>>>>>>>> 
>>>>>>>> “node.folder.key” is not correct. “folder” is a local variable of an un related object type.
>>>>>>>> 
>>>>>>>> I assume this broke with the recent XML filter changes.
>>>>>>>> 
>>>>>>>> Harbs
> 
> 
> 


Re: XML filters broke

Posted by Alex Harui <ah...@adobe.com.INVALID>.
EmitterUtils.writeThis seems to be working ok.  I think it would be better/correct to use it here.  I'm not sure if node as a parameter creates the same scope chain as node being the this pointer.  I think no, I don't think parameters are involved in lexical scoping.   IMO, 6a in the spec is saying we should make node the 'this' pointer in JS.

My 2 cents,
-Alex

On 8/7/18, 10:54 AM, "Harbs" <ha...@gmail.com> wrote:

    I’m not following you. Wouldn’t we need the same logic to figure out where to insert “this”? I’m not sure what practical difference there would be between “node" and “this”, other than using apply or call. Passing in the XML node seems cleaner to me.
    
    > On Aug 7, 2018, at 6:50 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    > 
    > Yup.  After thinking about it some more, it occurs to me that we took the wrong starting point.  Right now code like:
    > 
    > over40(parseInt(age))
    > 
    > Results in:
    > 
    > function(node) { return (over40(parseInt(age))) }
    > 
    > And then the XML filter calls that function passing itself in as the node.
    > 
    > And this discussion has been about trying to figure out where to add the "node" parameter.  But now I think that 6a in the spec is really saying that the 'this' pointer should be the node.  We should transpile that filter expression like any other function body but assume it is a function run in the context of the node, like a new method on XML/XMLList, or maybe more like an anonymous function.
    > 
    > So if I'm right, then the output should be:
    > 
    > function() { return (over40(parseInt(this.age))) }
    > 
    > This is what the transpiler would have output if you had subclassed XML and added this method to it.  And then the code in XML.SWC that applies the filter has to use Function.apply/call passing the node as the 'this' pointer.
    > 
    > If we do that, then the EmitterUtils.writeE4xFilterNode would go away, and JSRoyaleEmitter.emitE4xFilter would temporarily change the model.currentClass and maybe a few other things to reference an XML object.
    > 
    > Thoughts?
    > -Alex
    > 
    > PS: Regarding adding tests, the filter tests have two variables.  "var a" sets up the XML, "var b" is the result of the filter.  getVariable returns the nodes for "a" then we go get child(1) which is "b" and then emit it to see what we get.
    > 
    > On 8/7/18, 3:51 AM, "Harbs" <harbs.lists@gmail.com <ma...@gmail.com>> wrote:
    > 
    >    I’m also pretty sure that the following from Mozilla’s page[1] will not work correctly:
    > 
    >    var people = <people>
    >      <person>
    >        <name>Bob</name>
    >        <age>32</age>
    >      </person>
    >      <person>
    >        <name>Joe</name>
    >        <age>46</age>
    >      </person>
    >    </people>;
    > 
    >    function over40(i) {
    >        return i > 40;
    >    }
    > 
    >    alert(people.person.(over40(parseInt(age))).name); // Alerts Joe
    > 
    >    https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C47aa707c6e664beeafe308d5fc53afbd%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636692358717325505&amp;sdata=I1dJz1%2BApUMPtSZNoFFWF68u1IeygB6fiIF%2FKM9zq4Y%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C47aa707c6e664beeafe308d5fc53afbd%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636692358717325505&amp;sdata=I1dJz1%2BApUMPtSZNoFFWF68u1IeygB6fiIF%2FKM9zq4Y%3D&amp;reserved=0> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C47aa707c6e664beeafe308d5fc53afbd%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636692358717325505&amp;sdata=I1dJz1%2BApUMPtSZNoFFWF68u1IeygB6fiIF%2FKM9zq4Y%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C47aa707c6e664beeafe308d5fc53afbd%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636692358717325505&amp;sdata=I1dJz1%2BApUMPtSZNoFFWF68u1IeygB6fiIF%2FKM9zq4Y%3D&amp;reserved=0>>
    > 
    >> On Aug 7, 2018, at 1:41 PM, Harbs <ha...@gmail.com> wrote:
    >> 
    >> OK. I fixed the issue, but there’s a couple of loose ends:
    >> 
    >> 1. I don’t know how to add unit tests for these cases. In the current unit tests, I see “getNode” and “getVariable” being used. I don’t know the logic in setting up tests.
    >> 2. I’m not quite sure what "parentNode.getChild(0)” does. What is the parent node and will this cause my second case of e.employee.(1 == @id) to fail? Removing the check against firstChild caused the testXMLFilterWithAttribute test to fail because it prepended “node.” to “length()”.
    >> 
    >> P.S. I finally got debugging from Eclipse working on the compiler, so hopefully I’ll have a much easier time fixing compiler issues in the future. :-)
    >> 
    >> Thanks,
    >> Harbs
    >> 
    >>> On Aug 7, 2018, at 10:51 AM, Harbs <ha...@gmail.com> wrote:
    >>> 
    >>> Well, it looks like I was wrong.
    >>> 
    >>> I just tested the following in Flash, and then both give the same results (i.e. return the attribute):
    >>> 
    >>> var emp = e.employee.(@id == 1).@name; // name of employee with id 1
    >>> var foo = e.employee.(1 == @id).@name; // name of employee with id 1
    >>> 
    >>>> On Aug 7, 2018, at 10:27 AM, Harbs <ha...@gmail.com> wrote:
    >>>> 
    >>>> Your example does not seem to be right to me.
    >>>> 
    >>>> Here’s the overview of how filters are supposed to work from the spec:
    >>>> 
    >>>>> Overview
    >>>>> When the left operand evaluates to an XML object, the filtering predicate adds the left operand to the front of the scope chain of the current execution context, evaluates the Expression with the augmented scope chain, converts the result to a Boolean value, then restores the scope chain. If the result is true, the filtering predicate returns an XMLList containing the left operand. Otherwise it returns an empty XMLList.
    >>>>> When the left operand is an XMLList, the filtering predicate is applied to each XML object in the XMLList in order using the XML object as the left operand and the Expression as the right operand. It concatenates the results and returns them as a single XMLList containing all the XML properties for which the result was true. For example,
    >>>>> 
    >>>>> var john = e.employee.(name == "John"); // employees with name John
    >>>>> var twoemployees = e.employee.(@id == 0 || @id == 1); // employees with id's 0 & 1
    >>>>> var emp = e.employee.(@id == 1).name; // name of employee with id 1
    >>>>> 
    >>>>> The effect of the filtering predicate is similar to SQL’s WHERE clause or XPath’s filtering predicates.
    >>>>> For example, the statement:
    >>>>> 
    >>>>> // get the two employees with ids 0 and 1 using a predicate
    >>>>> var twoEmployees = e..employee.(@id == 0 || @id == 1);
    >>>>> 
    >>>>> produces the same result as the following set of statements:
    >>>>> // get the two employees with the ids 0 and 1 using a for loop
    >>>>> var i = 0;
    >>>>> var twoEmployees = new XMLList();
    >>>>> for each (var p in e..employee) {
    >>>>> with (p) {
    >>>>> if (@id == 0 || @id == 1) {
    >>>>>   twoEmployees[i++] = p;
    >>>>> }
    >>>>> }
    >>>>> }
    >>>> 
    >>>> The question is what is "the front of the scope chain of the current execution context”? I’m pretty sure that means the start of sub-expressions. I don’t see how that can apply to the right-hand of comparison expressions. There is nothing in the spec about figuring out if a part of an expression is referring to XML or XMLList.
    >>>> 
    >>>>> On Aug 7, 2018, at 9:45 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >>>>> 
    >>>>> I don't get what portion of the spec has to do with whether we append "node" to various expressions.  IMO, the changes I made only affect 6b.  6a is handled by generating a function with "node" as the parameter (because node is list[i] in the spec).  The task in 6b is to correctly evaluate any e4x filter expression.  I'm not sure what the limits are on what you can have in a filter expression, but if you can have just plain "@app" anywhere in the filter expression, I don't believe scoping rules would know to apply that to the "node" parameter without generating the "node" before "@app".
    >>>>> 
    >>>>> There is a chance that the Flex Compiler was using "magic" to generate the "node" and really should have reported an error.  I do remember being told that the filter function can be "anything".  Even:
    >>>>> (var foo:int = @app.length(); foo > @bar.length())  
    >>>>> 
    >>>>> If there are actual rules in the spec about evaluating the expression, that might apply to how we handle these expressions, otherwise I think the right thing is to resolve each expression and if the expression does not resolve to anything else, assume that it applies to the node.   I know the logic in EmitterUtils.writeE4xFilterNode isn't covering all cases.  It is trying to see what the expression resolves to, and returns false for known conditions (like a member of a class).  Just make it return false for your case (and feel free to add that case to the tests).  Eventually we'll have enough cases to either call it "good enough" or figure out a better way to determine when the expression applies to "node".
    >>>>> 
    >>>>> My 2 cents,
    >>>>> -Alex
    >>>>> 
    >>>>> On 8/6/18, 11:20 PM, "Harbs" <ha...@gmail.com> wrote:
    >>>>> 
    >>>>> I just looked at the spec. I think it’s correct to append “node” to the first statement of the expression only. The only exception seems to be expressions which use boolean expressions (i.e. || or &&) in which case each piece of the boolean expression should be considered a self-contained expression. So in your example, there are really two filter expressions:
    >>>>> 1. hasOwnProperty("@app”)
    >>>>> 2. @app.length() > 0
    >>>>> 
    >>>>> Both of those should have node appended to the front, but nothing else.
    >>>>> 
    >>>>> Here’s the relevant semantics in the spec (the important bit being 6a):
    >>>>> 
    >>>>>> 6. For i = 0 to list.[[Length]]-1
    >>>>>> a. Add list[i] to the front of the scope chain
    >>>>>> b. Let ref be the result of evaluating Expression using the augmented scope chain of step 6a
    >>>>>> c. Let match = ToBoolean(GetValue(ref))
    >>>>>> d. Remove list[i] from the front of the scope chain
    >>>>>> e. If (match == true), call the [[Append]] method of r with argument list[i]
    >>>>>> 7. Return r
    >>>>> 
    >>>>> Makes sense?
    >>>>> 
    >>>>> Harbs
    >>>>> 
    >>>>>> On Aug 7, 2018, at 1:39 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >>>>>> 
    >>>>>> In porting Tour De Flex, there were patterns like this (explorerTree is XML):
    >>>>>> 
    >>>>>> explorerTree..node.(hasOwnProperty("@app") && @app.length() > 0)
    >>>>>> 
    >>>>>> The compiler logic before I made any changes yesterday just assumed that the first expression was a reference to the node parameter but other expressions were not, but it looks like the expression "@app.length()" was allowed in Flex as a reference to the node.  So I think the compiler has to determine what expressions evaluate to "nothing" which implies they are references to the node, and what did resolve to something.  This is all new logic and I don't know how to determine all of the test cases up front, so we'll have to keep tuning it as we find patterns that don't work as we want them to.
    >>>>>> 
    >>>>>> In your case, if the expression resolves to a VariableDefinition, that probably means that isn't a reference to node.  Not exactly sure, so you should debug into it to see what the node pattern is and return false.
    >>>>>> 
    >>>>>> Thanks,
    >>>>>> -Alex
    >>>>>> 
    >>>>>> On 8/6/18, 3:28 PM, "Harbs" <ha...@gmail.com> wrote:
    >>>>>> 
    >>>>>> Doesn’t it always need to be a method for it to reference the node?
    >>>>>> 
    >>>>>> I.e. child() should be node.child(), but foo.baz would not.
    >>>>>> 
    >>>>>>> On Aug 7, 2018, at 1:12 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >>>>>>> 
    >>>>>>> Yep, we need more intelligent understanding of when a reference is to the node or not.
    >>>>>>> 
    >>>>>>> Debug into EmitterUtils.writeE4xFilterNode and figure out the node pattern you need.
    >>>>>>> 
    >>>>>>> -Alex
    >>>>>>> 
    >>>>>>> On 8/6/18, 3:09 PM, "Harbs" <ha...@gmail.com> wrote:
    >>>>>>> 
    >>>>>>> var folderFolders:XMLList = assetXML.folder.(child('key').indexOf(folder.key) == 0);
    >>>>>>> var folderImages:XMLList = assetXML.image.(child('key').indexOf(folder.key) == 0);
    >>>>>>> 
    >>>>>>> Is now compiled as:
    >>>>>>> 
    >>>>>>> var /** @type {XMLList} */ folderFolders = this.assetXML.child('folder').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
    >>>>>>> var /** @type {XMLList} */ folderImages = this.assetXML.child('image').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
    >>>>>>> 
    >>>>>>> “node.folder.key” is not correct. “folder” is a local variable of an un related object type.
    >>>>>>> 
    >>>>>>> I assume this broke with the recent XML filter changes.
    >>>>>>> 
    >>>>>>> Harbs
    
    


Re: XML filters broke

Posted by Harbs <ha...@gmail.com>.
I’m not following you. Wouldn’t we need the same logic to figure out where to insert “this”? I’m not sure what practical difference there would be between “node" and “this”, other than using apply or call. Passing in the XML node seems cleaner to me.

> On Aug 7, 2018, at 6:50 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
> 
> Yup.  After thinking about it some more, it occurs to me that we took the wrong starting point.  Right now code like:
> 
> over40(parseInt(age))
> 
> Results in:
> 
> function(node) { return (over40(parseInt(age))) }
> 
> And then the XML filter calls that function passing itself in as the node.
> 
> And this discussion has been about trying to figure out where to add the "node" parameter.  But now I think that 6a in the spec is really saying that the 'this' pointer should be the node.  We should transpile that filter expression like any other function body but assume it is a function run in the context of the node, like a new method on XML/XMLList, or maybe more like an anonymous function.
> 
> So if I'm right, then the output should be:
> 
> function() { return (over40(parseInt(this.age))) }
> 
> This is what the transpiler would have output if you had subclassed XML and added this method to it.  And then the code in XML.SWC that applies the filter has to use Function.apply/call passing the node as the 'this' pointer.
> 
> If we do that, then the EmitterUtils.writeE4xFilterNode would go away, and JSRoyaleEmitter.emitE4xFilter would temporarily change the model.currentClass and maybe a few other things to reference an XML object.
> 
> Thoughts?
> -Alex
> 
> PS: Regarding adding tests, the filter tests have two variables.  "var a" sets up the XML, "var b" is the result of the filter.  getVariable returns the nodes for "a" then we go get child(1) which is "b" and then emit it to see what we get.
> 
> On 8/7/18, 3:51 AM, "Harbs" <harbs.lists@gmail.com <ma...@gmail.com>> wrote:
> 
>    I’m also pretty sure that the following from Mozilla’s page[1] will not work correctly:
> 
>    var people = <people>
>      <person>
>        <name>Bob</name>
>        <age>32</age>
>      </person>
>      <person>
>        <name>Joe</name>
>        <age>46</age>
>      </person>
>    </people>;
> 
>    function over40(i) {
>        return i > 40;
>    }
> 
>    alert(people.person.(over40(parseInt(age))).name); // Alerts Joe
> 
>    https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C47aa707c6e664beeafe308d5fc53afbd%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636692358717325505&amp;sdata=I1dJz1%2BApUMPtSZNoFFWF68u1IeygB6fiIF%2FKM9zq4Y%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C47aa707c6e664beeafe308d5fc53afbd%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636692358717325505&amp;sdata=I1dJz1%2BApUMPtSZNoFFWF68u1IeygB6fiIF%2FKM9zq4Y%3D&amp;reserved=0> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C47aa707c6e664beeafe308d5fc53afbd%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636692358717325505&amp;sdata=I1dJz1%2BApUMPtSZNoFFWF68u1IeygB6fiIF%2FKM9zq4Y%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C47aa707c6e664beeafe308d5fc53afbd%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636692358717325505&amp;sdata=I1dJz1%2BApUMPtSZNoFFWF68u1IeygB6fiIF%2FKM9zq4Y%3D&amp;reserved=0>>
> 
>> On Aug 7, 2018, at 1:41 PM, Harbs <ha...@gmail.com> wrote:
>> 
>> OK. I fixed the issue, but there’s a couple of loose ends:
>> 
>> 1. I don’t know how to add unit tests for these cases. In the current unit tests, I see “getNode” and “getVariable” being used. I don’t know the logic in setting up tests.
>> 2. I’m not quite sure what "parentNode.getChild(0)” does. What is the parent node and will this cause my second case of e.employee.(1 == @id) to fail? Removing the check against firstChild caused the testXMLFilterWithAttribute test to fail because it prepended “node.” to “length()”.
>> 
>> P.S. I finally got debugging from Eclipse working on the compiler, so hopefully I’ll have a much easier time fixing compiler issues in the future. :-)
>> 
>> Thanks,
>> Harbs
>> 
>>> On Aug 7, 2018, at 10:51 AM, Harbs <ha...@gmail.com> wrote:
>>> 
>>> Well, it looks like I was wrong.
>>> 
>>> I just tested the following in Flash, and then both give the same results (i.e. return the attribute):
>>> 
>>> var emp = e.employee.(@id == 1).@name; // name of employee with id 1
>>> var foo = e.employee.(1 == @id).@name; // name of employee with id 1
>>> 
>>>> On Aug 7, 2018, at 10:27 AM, Harbs <ha...@gmail.com> wrote:
>>>> 
>>>> Your example does not seem to be right to me.
>>>> 
>>>> Here’s the overview of how filters are supposed to work from the spec:
>>>> 
>>>>> Overview
>>>>> When the left operand evaluates to an XML object, the filtering predicate adds the left operand to the front of the scope chain of the current execution context, evaluates the Expression with the augmented scope chain, converts the result to a Boolean value, then restores the scope chain. If the result is true, the filtering predicate returns an XMLList containing the left operand. Otherwise it returns an empty XMLList.
>>>>> When the left operand is an XMLList, the filtering predicate is applied to each XML object in the XMLList in order using the XML object as the left operand and the Expression as the right operand. It concatenates the results and returns them as a single XMLList containing all the XML properties for which the result was true. For example,
>>>>> 
>>>>> var john = e.employee.(name == "John"); // employees with name John
>>>>> var twoemployees = e.employee.(@id == 0 || @id == 1); // employees with id's 0 & 1
>>>>> var emp = e.employee.(@id == 1).name; // name of employee with id 1
>>>>> 
>>>>> The effect of the filtering predicate is similar to SQL’s WHERE clause or XPath’s filtering predicates.
>>>>> For example, the statement:
>>>>> 
>>>>> // get the two employees with ids 0 and 1 using a predicate
>>>>> var twoEmployees = e..employee.(@id == 0 || @id == 1);
>>>>> 
>>>>> produces the same result as the following set of statements:
>>>>> // get the two employees with the ids 0 and 1 using a for loop
>>>>> var i = 0;
>>>>> var twoEmployees = new XMLList();
>>>>> for each (var p in e..employee) {
>>>>> with (p) {
>>>>> if (@id == 0 || @id == 1) {
>>>>>   twoEmployees[i++] = p;
>>>>> }
>>>>> }
>>>>> }
>>>> 
>>>> The question is what is "the front of the scope chain of the current execution context”? I’m pretty sure that means the start of sub-expressions. I don’t see how that can apply to the right-hand of comparison expressions. There is nothing in the spec about figuring out if a part of an expression is referring to XML or XMLList.
>>>> 
>>>>> On Aug 7, 2018, at 9:45 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>>> 
>>>>> I don't get what portion of the spec has to do with whether we append "node" to various expressions.  IMO, the changes I made only affect 6b.  6a is handled by generating a function with "node" as the parameter (because node is list[i] in the spec).  The task in 6b is to correctly evaluate any e4x filter expression.  I'm not sure what the limits are on what you can have in a filter expression, but if you can have just plain "@app" anywhere in the filter expression, I don't believe scoping rules would know to apply that to the "node" parameter without generating the "node" before "@app".
>>>>> 
>>>>> There is a chance that the Flex Compiler was using "magic" to generate the "node" and really should have reported an error.  I do remember being told that the filter function can be "anything".  Even:
>>>>> (var foo:int = @app.length(); foo > @bar.length())  
>>>>> 
>>>>> If there are actual rules in the spec about evaluating the expression, that might apply to how we handle these expressions, otherwise I think the right thing is to resolve each expression and if the expression does not resolve to anything else, assume that it applies to the node.   I know the logic in EmitterUtils.writeE4xFilterNode isn't covering all cases.  It is trying to see what the expression resolves to, and returns false for known conditions (like a member of a class).  Just make it return false for your case (and feel free to add that case to the tests).  Eventually we'll have enough cases to either call it "good enough" or figure out a better way to determine when the expression applies to "node".
>>>>> 
>>>>> My 2 cents,
>>>>> -Alex
>>>>> 
>>>>> On 8/6/18, 11:20 PM, "Harbs" <ha...@gmail.com> wrote:
>>>>> 
>>>>> I just looked at the spec. I think it’s correct to append “node” to the first statement of the expression only. The only exception seems to be expressions which use boolean expressions (i.e. || or &&) in which case each piece of the boolean expression should be considered a self-contained expression. So in your example, there are really two filter expressions:
>>>>> 1. hasOwnProperty("@app”)
>>>>> 2. @app.length() > 0
>>>>> 
>>>>> Both of those should have node appended to the front, but nothing else.
>>>>> 
>>>>> Here’s the relevant semantics in the spec (the important bit being 6a):
>>>>> 
>>>>>> 6. For i = 0 to list.[[Length]]-1
>>>>>> a. Add list[i] to the front of the scope chain
>>>>>> b. Let ref be the result of evaluating Expression using the augmented scope chain of step 6a
>>>>>> c. Let match = ToBoolean(GetValue(ref))
>>>>>> d. Remove list[i] from the front of the scope chain
>>>>>> e. If (match == true), call the [[Append]] method of r with argument list[i]
>>>>>> 7. Return r
>>>>> 
>>>>> Makes sense?
>>>>> 
>>>>> Harbs
>>>>> 
>>>>>> On Aug 7, 2018, at 1:39 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>>>> 
>>>>>> In porting Tour De Flex, there were patterns like this (explorerTree is XML):
>>>>>> 
>>>>>> explorerTree..node.(hasOwnProperty("@app") && @app.length() > 0)
>>>>>> 
>>>>>> The compiler logic before I made any changes yesterday just assumed that the first expression was a reference to the node parameter but other expressions were not, but it looks like the expression "@app.length()" was allowed in Flex as a reference to the node.  So I think the compiler has to determine what expressions evaluate to "nothing" which implies they are references to the node, and what did resolve to something.  This is all new logic and I don't know how to determine all of the test cases up front, so we'll have to keep tuning it as we find patterns that don't work as we want them to.
>>>>>> 
>>>>>> In your case, if the expression resolves to a VariableDefinition, that probably means that isn't a reference to node.  Not exactly sure, so you should debug into it to see what the node pattern is and return false.
>>>>>> 
>>>>>> Thanks,
>>>>>> -Alex
>>>>>> 
>>>>>> On 8/6/18, 3:28 PM, "Harbs" <ha...@gmail.com> wrote:
>>>>>> 
>>>>>> Doesn’t it always need to be a method for it to reference the node?
>>>>>> 
>>>>>> I.e. child() should be node.child(), but foo.baz would not.
>>>>>> 
>>>>>>> On Aug 7, 2018, at 1:12 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>>>>> 
>>>>>>> Yep, we need more intelligent understanding of when a reference is to the node or not.
>>>>>>> 
>>>>>>> Debug into EmitterUtils.writeE4xFilterNode and figure out the node pattern you need.
>>>>>>> 
>>>>>>> -Alex
>>>>>>> 
>>>>>>> On 8/6/18, 3:09 PM, "Harbs" <ha...@gmail.com> wrote:
>>>>>>> 
>>>>>>> var folderFolders:XMLList = assetXML.folder.(child('key').indexOf(folder.key) == 0);
>>>>>>> var folderImages:XMLList = assetXML.image.(child('key').indexOf(folder.key) == 0);
>>>>>>> 
>>>>>>> Is now compiled as:
>>>>>>> 
>>>>>>> var /** @type {XMLList} */ folderFolders = this.assetXML.child('folder').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
>>>>>>> var /** @type {XMLList} */ folderImages = this.assetXML.child('image').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
>>>>>>> 
>>>>>>> “node.folder.key” is not correct. “folder” is a local variable of an un related object type.
>>>>>>> 
>>>>>>> I assume this broke with the recent XML filter changes.
>>>>>>> 
>>>>>>> Harbs


Re: XML filters broke

Posted by Harbs <ha...@gmail.com>.
I’m pretty sure that right now, we’d get:

function(node) { return (node.over40(parseInt(node.age))) }

Am I wrong?

> On Aug 7, 2018, at 6:50 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
> 
> Right now code like:
> 
> over40(parseInt(age))
> 
> Results in:
> 
> function(node) { return (over40(parseInt(age))) }
> 
> And then the XML filter calls that function passing itself in as the node.


Re: XML filters broke

Posted by Alex Harui <ah...@adobe.com.INVALID>.
Yup.  After thinking about it some more, it occurs to me that we took the wrong starting point.  Right now code like:

over40(parseInt(age))

Results in:

function(node) { return (over40(parseInt(age))) }

And then the XML filter calls that function passing itself in as the node.

And this discussion has been about trying to figure out where to add the "node" parameter.  But now I think that 6a in the spec is really saying that the 'this' pointer should be the node.  We should transpile that filter expression like any other function body but assume it is a function run in the context of the node, like a new method on XML/XMLList, or maybe more like an anonymous function.

So if I'm right, then the output should be:

function() { return (over40(parseInt(this.age))) }

This is what the transpiler would have output if you had subclassed XML and added this method to it.  And then the code in XML.SWC that applies the filter has to use Function.apply/call passing the node as the 'this' pointer.

If we do that, then the EmitterUtils.writeE4xFilterNode would go away, and JSRoyaleEmitter.emitE4xFilter would temporarily change the model.currentClass and maybe a few other things to reference an XML object.

Thoughts?
-Alex

PS: Regarding adding tests, the filter tests have two variables.  "var a" sets up the XML, "var b" is the result of the filter.  getVariable returns the nodes for "a" then we go get child(1) which is "b" and then emit it to see what we get.

On 8/7/18, 3:51 AM, "Harbs" <ha...@gmail.com> wrote:

    I’m also pretty sure that the following from Mozilla’s page[1] will not work correctly:
    
    var people = <people>
      <person>
        <name>Bob</name>
        <age>32</age>
      </person>
      <person>
        <name>Joe</name>
        <age>46</age>
      </person>
    </people>;
    
    function over40(i) {
        return i > 40;
    }
    
    alert(people.person.(over40(parseInt(age))).name); // Alerts Joe
    
    https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C47aa707c6e664beeafe308d5fc53afbd%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636692358717325505&amp;sdata=I1dJz1%2BApUMPtSZNoFFWF68u1IeygB6fiIF%2FKM9zq4Y%3D&amp;reserved=0 <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FArchive%2FWeb%2FE4X%2FProcessing_XML_with_E4X&amp;data=02%7C01%7Caharui%40adobe.com%7C47aa707c6e664beeafe308d5fc53afbd%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636692358717325505&amp;sdata=I1dJz1%2BApUMPtSZNoFFWF68u1IeygB6fiIF%2FKM9zq4Y%3D&amp;reserved=0>
    
    > On Aug 7, 2018, at 1:41 PM, Harbs <ha...@gmail.com> wrote:
    > 
    > OK. I fixed the issue, but there’s a couple of loose ends:
    > 
    > 1. I don’t know how to add unit tests for these cases. In the current unit tests, I see “getNode” and “getVariable” being used. I don’t know the logic in setting up tests.
    > 2. I’m not quite sure what "parentNode.getChild(0)” does. What is the parent node and will this cause my second case of e.employee.(1 == @id) to fail? Removing the check against firstChild caused the testXMLFilterWithAttribute test to fail because it prepended “node.” to “length()”.
    > 
    > P.S. I finally got debugging from Eclipse working on the compiler, so hopefully I’ll have a much easier time fixing compiler issues in the future. :-)
    > 
    > Thanks,
    > Harbs
    > 
    >> On Aug 7, 2018, at 10:51 AM, Harbs <ha...@gmail.com> wrote:
    >> 
    >> Well, it looks like I was wrong.
    >> 
    >> I just tested the following in Flash, and then both give the same results (i.e. return the attribute):
    >> 
    >> var emp = e.employee.(@id == 1).@name; // name of employee with id 1
    >> var foo = e.employee.(1 == @id).@name; // name of employee with id 1
    >> 
    >>> On Aug 7, 2018, at 10:27 AM, Harbs <ha...@gmail.com> wrote:
    >>> 
    >>> Your example does not seem to be right to me.
    >>> 
    >>> Here’s the overview of how filters are supposed to work from the spec:
    >>> 
    >>>> Overview
    >>>> When the left operand evaluates to an XML object, the filtering predicate adds the left operand to the front of the scope chain of the current execution context, evaluates the Expression with the augmented scope chain, converts the result to a Boolean value, then restores the scope chain. If the result is true, the filtering predicate returns an XMLList containing the left operand. Otherwise it returns an empty XMLList.
    >>>> When the left operand is an XMLList, the filtering predicate is applied to each XML object in the XMLList in order using the XML object as the left operand and the Expression as the right operand. It concatenates the results and returns them as a single XMLList containing all the XML properties for which the result was true. For example,
    >>>> 
    >>>> var john = e.employee.(name == "John"); // employees with name John
    >>>> var twoemployees = e.employee.(@id == 0 || @id == 1); // employees with id's 0 & 1
    >>>> var emp = e.employee.(@id == 1).name; // name of employee with id 1
    >>>> 
    >>>> The effect of the filtering predicate is similar to SQL’s WHERE clause or XPath’s filtering predicates.
    >>>> For example, the statement:
    >>>> 
    >>>> // get the two employees with ids 0 and 1 using a predicate
    >>>> var twoEmployees = e..employee.(@id == 0 || @id == 1);
    >>>> 
    >>>> produces the same result as the following set of statements:
    >>>> // get the two employees with the ids 0 and 1 using a for loop
    >>>> var i = 0;
    >>>> var twoEmployees = new XMLList();
    >>>> for each (var p in e..employee) {
    >>>> with (p) {
    >>>>  if (@id == 0 || @id == 1) {
    >>>>    twoEmployees[i++] = p;
    >>>>  }
    >>>> }
    >>>> }
    >>> 
    >>> The question is what is "the front of the scope chain of the current execution context”? I’m pretty sure that means the start of sub-expressions. I don’t see how that can apply to the right-hand of comparison expressions. There is nothing in the spec about figuring out if a part of an expression is referring to XML or XMLList.
    >>> 
    >>>> On Aug 7, 2018, at 9:45 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >>>> 
    >>>> I don't get what portion of the spec has to do with whether we append "node" to various expressions.  IMO, the changes I made only affect 6b.  6a is handled by generating a function with "node" as the parameter (because node is list[i] in the spec).  The task in 6b is to correctly evaluate any e4x filter expression.  I'm not sure what the limits are on what you can have in a filter expression, but if you can have just plain "@app" anywhere in the filter expression, I don't believe scoping rules would know to apply that to the "node" parameter without generating the "node" before "@app".
    >>>> 
    >>>> There is a chance that the Flex Compiler was using "magic" to generate the "node" and really should have reported an error.  I do remember being told that the filter function can be "anything".  Even:
    >>>> (var foo:int = @app.length(); foo > @bar.length())  
    >>>> 
    >>>> If there are actual rules in the spec about evaluating the expression, that might apply to how we handle these expressions, otherwise I think the right thing is to resolve each expression and if the expression does not resolve to anything else, assume that it applies to the node.   I know the logic in EmitterUtils.writeE4xFilterNode isn't covering all cases.  It is trying to see what the expression resolves to, and returns false for known conditions (like a member of a class).  Just make it return false for your case (and feel free to add that case to the tests).  Eventually we'll have enough cases to either call it "good enough" or figure out a better way to determine when the expression applies to "node".
    >>>> 
    >>>> My 2 cents,
    >>>> -Alex
    >>>> 
    >>>> On 8/6/18, 11:20 PM, "Harbs" <ha...@gmail.com> wrote:
    >>>> 
    >>>> I just looked at the spec. I think it’s correct to append “node” to the first statement of the expression only. The only exception seems to be expressions which use boolean expressions (i.e. || or &&) in which case each piece of the boolean expression should be considered a self-contained expression. So in your example, there are really two filter expressions:
    >>>> 1. hasOwnProperty("@app”)
    >>>> 2. @app.length() > 0
    >>>> 
    >>>> Both of those should have node appended to the front, but nothing else.
    >>>> 
    >>>> Here’s the relevant semantics in the spec (the important bit being 6a):
    >>>> 
    >>>>> 6. For i = 0 to list.[[Length]]-1
    >>>>> a. Add list[i] to the front of the scope chain
    >>>>> b. Let ref be the result of evaluating Expression using the augmented scope chain of step 6a
    >>>>> c. Let match = ToBoolean(GetValue(ref))
    >>>>> d. Remove list[i] from the front of the scope chain
    >>>>> e. If (match == true), call the [[Append]] method of r with argument list[i]
    >>>>> 7. Return r
    >>>> 
    >>>> Makes sense?
    >>>> 
    >>>> Harbs
    >>>> 
    >>>>> On Aug 7, 2018, at 1:39 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >>>>> 
    >>>>> In porting Tour De Flex, there were patterns like this (explorerTree is XML):
    >>>>> 
    >>>>> explorerTree..node.(hasOwnProperty("@app") && @app.length() > 0)
    >>>>> 
    >>>>> The compiler logic before I made any changes yesterday just assumed that the first expression was a reference to the node parameter but other expressions were not, but it looks like the expression "@app.length()" was allowed in Flex as a reference to the node.  So I think the compiler has to determine what expressions evaluate to "nothing" which implies they are references to the node, and what did resolve to something.  This is all new logic and I don't know how to determine all of the test cases up front, so we'll have to keep tuning it as we find patterns that don't work as we want them to.
    >>>>> 
    >>>>> In your case, if the expression resolves to a VariableDefinition, that probably means that isn't a reference to node.  Not exactly sure, so you should debug into it to see what the node pattern is and return false.
    >>>>> 
    >>>>> Thanks,
    >>>>> -Alex
    >>>>> 
    >>>>> On 8/6/18, 3:28 PM, "Harbs" <ha...@gmail.com> wrote:
    >>>>> 
    >>>>> Doesn’t it always need to be a method for it to reference the node?
    >>>>> 
    >>>>> I.e. child() should be node.child(), but foo.baz would not.
    >>>>> 
    >>>>>> On Aug 7, 2018, at 1:12 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >>>>>> 
    >>>>>> Yep, we need more intelligent understanding of when a reference is to the node or not.
    >>>>>> 
    >>>>>> Debug into EmitterUtils.writeE4xFilterNode and figure out the node pattern you need.
    >>>>>> 
    >>>>>> -Alex
    >>>>>> 
    >>>>>> On 8/6/18, 3:09 PM, "Harbs" <ha...@gmail.com> wrote:
    >>>>>> 
    >>>>>> var folderFolders:XMLList = assetXML.folder.(child('key').indexOf(folder.key) == 0);
    >>>>>> var folderImages:XMLList = assetXML.image.(child('key').indexOf(folder.key) == 0);
    >>>>>> 
    >>>>>> Is now compiled as:
    >>>>>> 
    >>>>>> var /** @type {XMLList} */ folderFolders = this.assetXML.child('folder').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
    >>>>>> var /** @type {XMLList} */ folderImages = this.assetXML.child('image').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
    >>>>>> 
    >>>>>> “node.folder.key” is not correct. “folder” is a local variable of an un related object type.
    >>>>>> 
    >>>>>> I assume this broke with the recent XML filter changes.
    >>>>>> 
    >>>>>> Harbs
    >>>>>> 
    >>>>> 
    >>>>> 
    >>>>> 
    >>>> 
    >>>> 
    >>>> 
    >>> 
    >> 
    > 
    
    


Re: XML filters broke

Posted by Harbs <ha...@gmail.com>.
I’m also pretty sure that the following from Mozilla’s page[1] will not work correctly:

var people = <people>
  <person>
    <name>Bob</name>
    <age>32</age>
  </person>
  <person>
    <name>Joe</name>
    <age>46</age>
  </person>
</people>;

function over40(i) {
    return i > 40;
}

alert(people.person.(over40(parseInt(age))).name); // Alerts Joe

https://developer.mozilla.org/en-US/docs/Archive/Web/E4X/Processing_XML_with_E4X <https://developer.mozilla.org/en-US/docs/Archive/Web/E4X/Processing_XML_with_E4X>

> On Aug 7, 2018, at 1:41 PM, Harbs <ha...@gmail.com> wrote:
> 
> OK. I fixed the issue, but there’s a couple of loose ends:
> 
> 1. I don’t know how to add unit tests for these cases. In the current unit tests, I see “getNode” and “getVariable” being used. I don’t know the logic in setting up tests.
> 2. I’m not quite sure what "parentNode.getChild(0)” does. What is the parent node and will this cause my second case of e.employee.(1 == @id) to fail? Removing the check against firstChild caused the testXMLFilterWithAttribute test to fail because it prepended “node.” to “length()”.
> 
> P.S. I finally got debugging from Eclipse working on the compiler, so hopefully I’ll have a much easier time fixing compiler issues in the future. :-)
> 
> Thanks,
> Harbs
> 
>> On Aug 7, 2018, at 10:51 AM, Harbs <ha...@gmail.com> wrote:
>> 
>> Well, it looks like I was wrong.
>> 
>> I just tested the following in Flash, and then both give the same results (i.e. return the attribute):
>> 
>> var emp = e.employee.(@id == 1).@name; // name of employee with id 1
>> var foo = e.employee.(1 == @id).@name; // name of employee with id 1
>> 
>>> On Aug 7, 2018, at 10:27 AM, Harbs <ha...@gmail.com> wrote:
>>> 
>>> Your example does not seem to be right to me.
>>> 
>>> Here’s the overview of how filters are supposed to work from the spec:
>>> 
>>>> Overview
>>>> When the left operand evaluates to an XML object, the filtering predicate adds the left operand to the front of the scope chain of the current execution context, evaluates the Expression with the augmented scope chain, converts the result to a Boolean value, then restores the scope chain. If the result is true, the filtering predicate returns an XMLList containing the left operand. Otherwise it returns an empty XMLList.
>>>> When the left operand is an XMLList, the filtering predicate is applied to each XML object in the XMLList in order using the XML object as the left operand and the Expression as the right operand. It concatenates the results and returns them as a single XMLList containing all the XML properties for which the result was true. For example,
>>>> 
>>>> var john = e.employee.(name == "John"); // employees with name John
>>>> var twoemployees = e.employee.(@id == 0 || @id == 1); // employees with id's 0 & 1
>>>> var emp = e.employee.(@id == 1).name; // name of employee with id 1
>>>> 
>>>> The effect of the filtering predicate is similar to SQL’s WHERE clause or XPath’s filtering predicates.
>>>> For example, the statement:
>>>> 
>>>> // get the two employees with ids 0 and 1 using a predicate
>>>> var twoEmployees = e..employee.(@id == 0 || @id == 1);
>>>> 
>>>> produces the same result as the following set of statements:
>>>> // get the two employees with the ids 0 and 1 using a for loop
>>>> var i = 0;
>>>> var twoEmployees = new XMLList();
>>>> for each (var p in e..employee) {
>>>> with (p) {
>>>>  if (@id == 0 || @id == 1) {
>>>>    twoEmployees[i++] = p;
>>>>  }
>>>> }
>>>> }
>>> 
>>> The question is what is "the front of the scope chain of the current execution context”? I’m pretty sure that means the start of sub-expressions. I don’t see how that can apply to the right-hand of comparison expressions. There is nothing in the spec about figuring out if a part of an expression is referring to XML or XMLList.
>>> 
>>>> On Aug 7, 2018, at 9:45 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>> 
>>>> I don't get what portion of the spec has to do with whether we append "node" to various expressions.  IMO, the changes I made only affect 6b.  6a is handled by generating a function with "node" as the parameter (because node is list[i] in the spec).  The task in 6b is to correctly evaluate any e4x filter expression.  I'm not sure what the limits are on what you can have in a filter expression, but if you can have just plain "@app" anywhere in the filter expression, I don't believe scoping rules would know to apply that to the "node" parameter without generating the "node" before "@app".
>>>> 
>>>> There is a chance that the Flex Compiler was using "magic" to generate the "node" and really should have reported an error.  I do remember being told that the filter function can be "anything".  Even:
>>>> (var foo:int = @app.length(); foo > @bar.length())  
>>>> 
>>>> If there are actual rules in the spec about evaluating the expression, that might apply to how we handle these expressions, otherwise I think the right thing is to resolve each expression and if the expression does not resolve to anything else, assume that it applies to the node.   I know the logic in EmitterUtils.writeE4xFilterNode isn't covering all cases.  It is trying to see what the expression resolves to, and returns false for known conditions (like a member of a class).  Just make it return false for your case (and feel free to add that case to the tests).  Eventually we'll have enough cases to either call it "good enough" or figure out a better way to determine when the expression applies to "node".
>>>> 
>>>> My 2 cents,
>>>> -Alex
>>>> 
>>>> On 8/6/18, 11:20 PM, "Harbs" <ha...@gmail.com> wrote:
>>>> 
>>>> I just looked at the spec. I think it’s correct to append “node” to the first statement of the expression only. The only exception seems to be expressions which use boolean expressions (i.e. || or &&) in which case each piece of the boolean expression should be considered a self-contained expression. So in your example, there are really two filter expressions:
>>>> 1. hasOwnProperty("@app”)
>>>> 2. @app.length() > 0
>>>> 
>>>> Both of those should have node appended to the front, but nothing else.
>>>> 
>>>> Here’s the relevant semantics in the spec (the important bit being 6a):
>>>> 
>>>>> 6. For i = 0 to list.[[Length]]-1
>>>>> a. Add list[i] to the front of the scope chain
>>>>> b. Let ref be the result of evaluating Expression using the augmented scope chain of step 6a
>>>>> c. Let match = ToBoolean(GetValue(ref))
>>>>> d. Remove list[i] from the front of the scope chain
>>>>> e. If (match == true), call the [[Append]] method of r with argument list[i]
>>>>> 7. Return r
>>>> 
>>>> Makes sense?
>>>> 
>>>> Harbs
>>>> 
>>>>> On Aug 7, 2018, at 1:39 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>>> 
>>>>> In porting Tour De Flex, there were patterns like this (explorerTree is XML):
>>>>> 
>>>>> explorerTree..node.(hasOwnProperty("@app") && @app.length() > 0)
>>>>> 
>>>>> The compiler logic before I made any changes yesterday just assumed that the first expression was a reference to the node parameter but other expressions were not, but it looks like the expression "@app.length()" was allowed in Flex as a reference to the node.  So I think the compiler has to determine what expressions evaluate to "nothing" which implies they are references to the node, and what did resolve to something.  This is all new logic and I don't know how to determine all of the test cases up front, so we'll have to keep tuning it as we find patterns that don't work as we want them to.
>>>>> 
>>>>> In your case, if the expression resolves to a VariableDefinition, that probably means that isn't a reference to node.  Not exactly sure, so you should debug into it to see what the node pattern is and return false.
>>>>> 
>>>>> Thanks,
>>>>> -Alex
>>>>> 
>>>>> On 8/6/18, 3:28 PM, "Harbs" <ha...@gmail.com> wrote:
>>>>> 
>>>>> Doesn’t it always need to be a method for it to reference the node?
>>>>> 
>>>>> I.e. child() should be node.child(), but foo.baz would not.
>>>>> 
>>>>>> On Aug 7, 2018, at 1:12 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>>>> 
>>>>>> Yep, we need more intelligent understanding of when a reference is to the node or not.
>>>>>> 
>>>>>> Debug into EmitterUtils.writeE4xFilterNode and figure out the node pattern you need.
>>>>>> 
>>>>>> -Alex
>>>>>> 
>>>>>> On 8/6/18, 3:09 PM, "Harbs" <ha...@gmail.com> wrote:
>>>>>> 
>>>>>> var folderFolders:XMLList = assetXML.folder.(child('key').indexOf(folder.key) == 0);
>>>>>> var folderImages:XMLList = assetXML.image.(child('key').indexOf(folder.key) == 0);
>>>>>> 
>>>>>> Is now compiled as:
>>>>>> 
>>>>>> var /** @type {XMLList} */ folderFolders = this.assetXML.child('folder').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
>>>>>> var /** @type {XMLList} */ folderImages = this.assetXML.child('image').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
>>>>>> 
>>>>>> “node.folder.key” is not correct. “folder” is a local variable of an un related object type.
>>>>>> 
>>>>>> I assume this broke with the recent XML filter changes.
>>>>>> 
>>>>>> Harbs
>>>>>> 
>>>>> 
>>>>> 
>>>>> 
>>>> 
>>>> 
>>>> 
>>> 
>> 
> 


Re: XML filters broke

Posted by Harbs <ha...@gmail.com>.
OK. I fixed the issue, but there’s a couple of loose ends:

1. I don’t know how to add unit tests for these cases. In the current unit tests, I see “getNode” and “getVariable” being used. I don’t know the logic in setting up tests.
2. I’m not quite sure what "parentNode.getChild(0)” does. What is the parent node and will this cause my second case of e.employee.(1 == @id) to fail? Removing the check against firstChild caused the testXMLFilterWithAttribute test to fail because it prepended “node.” to “length()”.

P.S. I finally got debugging from Eclipse working on the compiler, so hopefully I’ll have a much easier time fixing compiler issues in the future. :-)

Thanks,
Harbs

> On Aug 7, 2018, at 10:51 AM, Harbs <ha...@gmail.com> wrote:
> 
> Well, it looks like I was wrong.
> 
> I just tested the following in Flash, and then both give the same results (i.e. return the attribute):
> 
> var emp = e.employee.(@id == 1).@name; // name of employee with id 1
> var foo = e.employee.(1 == @id).@name; // name of employee with id 1
> 
>> On Aug 7, 2018, at 10:27 AM, Harbs <ha...@gmail.com> wrote:
>> 
>> Your example does not seem to be right to me.
>> 
>> Here’s the overview of how filters are supposed to work from the spec:
>> 
>>> Overview
>>> When the left operand evaluates to an XML object, the filtering predicate adds the left operand to the front of the scope chain of the current execution context, evaluates the Expression with the augmented scope chain, converts the result to a Boolean value, then restores the scope chain. If the result is true, the filtering predicate returns an XMLList containing the left operand. Otherwise it returns an empty XMLList.
>>> When the left operand is an XMLList, the filtering predicate is applied to each XML object in the XMLList in order using the XML object as the left operand and the Expression as the right operand. It concatenates the results and returns them as a single XMLList containing all the XML properties for which the result was true. For example,
>>> 
>>> var john = e.employee.(name == "John"); // employees with name John
>>> var twoemployees = e.employee.(@id == 0 || @id == 1); // employees with id's 0 & 1
>>> var emp = e.employee.(@id == 1).name; // name of employee with id 1
>>> 
>>> The effect of the filtering predicate is similar to SQL’s WHERE clause or XPath’s filtering predicates.
>>> For example, the statement:
>>> 
>>> // get the two employees with ids 0 and 1 using a predicate
>>> var twoEmployees = e..employee.(@id == 0 || @id == 1);
>>> 
>>> produces the same result as the following set of statements:
>>> // get the two employees with the ids 0 and 1 using a for loop
>>> var i = 0;
>>> var twoEmployees = new XMLList();
>>> for each (var p in e..employee) {
>>> with (p) {
>>>   if (@id == 0 || @id == 1) {
>>>     twoEmployees[i++] = p;
>>>   }
>>> }
>>> }
>> 
>> The question is what is "the front of the scope chain of the current execution context”? I’m pretty sure that means the start of sub-expressions. I don’t see how that can apply to the right-hand of comparison expressions. There is nothing in the spec about figuring out if a part of an expression is referring to XML or XMLList.
>> 
>>> On Aug 7, 2018, at 9:45 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>> 
>>> I don't get what portion of the spec has to do with whether we append "node" to various expressions.  IMO, the changes I made only affect 6b.  6a is handled by generating a function with "node" as the parameter (because node is list[i] in the spec).  The task in 6b is to correctly evaluate any e4x filter expression.  I'm not sure what the limits are on what you can have in a filter expression, but if you can have just plain "@app" anywhere in the filter expression, I don't believe scoping rules would know to apply that to the "node" parameter without generating the "node" before "@app".
>>> 
>>> There is a chance that the Flex Compiler was using "magic" to generate the "node" and really should have reported an error.  I do remember being told that the filter function can be "anything".  Even:
>>> (var foo:int = @app.length(); foo > @bar.length())  
>>> 
>>> If there are actual rules in the spec about evaluating the expression, that might apply to how we handle these expressions, otherwise I think the right thing is to resolve each expression and if the expression does not resolve to anything else, assume that it applies to the node.   I know the logic in EmitterUtils.writeE4xFilterNode isn't covering all cases.  It is trying to see what the expression resolves to, and returns false for known conditions (like a member of a class).  Just make it return false for your case (and feel free to add that case to the tests).  Eventually we'll have enough cases to either call it "good enough" or figure out a better way to determine when the expression applies to "node".
>>> 
>>> My 2 cents,
>>> -Alex
>>> 
>>> On 8/6/18, 11:20 PM, "Harbs" <ha...@gmail.com> wrote:
>>> 
>>>  I just looked at the spec. I think it’s correct to append “node” to the first statement of the expression only. The only exception seems to be expressions which use boolean expressions (i.e. || or &&) in which case each piece of the boolean expression should be considered a self-contained expression. So in your example, there are really two filter expressions:
>>>  1. hasOwnProperty("@app”)
>>>  2. @app.length() > 0
>>> 
>>>  Both of those should have node appended to the front, but nothing else.
>>> 
>>>  Here’s the relevant semantics in the spec (the important bit being 6a):
>>> 
>>>> 6. For i = 0 to list.[[Length]]-1
>>>> a. Add list[i] to the front of the scope chain
>>>> b. Let ref be the result of evaluating Expression using the augmented scope chain of step 6a
>>>> c. Let match = ToBoolean(GetValue(ref))
>>>> d. Remove list[i] from the front of the scope chain
>>>> e. If (match == true), call the [[Append]] method of r with argument list[i]
>>>> 7. Return r
>>> 
>>>  Makes sense?
>>> 
>>>  Harbs
>>> 
>>>> On Aug 7, 2018, at 1:39 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>> 
>>>> In porting Tour De Flex, there were patterns like this (explorerTree is XML):
>>>> 
>>>> explorerTree..node.(hasOwnProperty("@app") && @app.length() > 0)
>>>> 
>>>> The compiler logic before I made any changes yesterday just assumed that the first expression was a reference to the node parameter but other expressions were not, but it looks like the expression "@app.length()" was allowed in Flex as a reference to the node.  So I think the compiler has to determine what expressions evaluate to "nothing" which implies they are references to the node, and what did resolve to something.  This is all new logic and I don't know how to determine all of the test cases up front, so we'll have to keep tuning it as we find patterns that don't work as we want them to.
>>>> 
>>>> In your case, if the expression resolves to a VariableDefinition, that probably means that isn't a reference to node.  Not exactly sure, so you should debug into it to see what the node pattern is and return false.
>>>> 
>>>> Thanks,
>>>> -Alex
>>>> 
>>>> On 8/6/18, 3:28 PM, "Harbs" <ha...@gmail.com> wrote:
>>>> 
>>>> Doesn’t it always need to be a method for it to reference the node?
>>>> 
>>>> I.e. child() should be node.child(), but foo.baz would not.
>>>> 
>>>>> On Aug 7, 2018, at 1:12 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>>> 
>>>>> Yep, we need more intelligent understanding of when a reference is to the node or not.
>>>>> 
>>>>> Debug into EmitterUtils.writeE4xFilterNode and figure out the node pattern you need.
>>>>> 
>>>>> -Alex
>>>>> 
>>>>> On 8/6/18, 3:09 PM, "Harbs" <ha...@gmail.com> wrote:
>>>>> 
>>>>> var folderFolders:XMLList = assetXML.folder.(child('key').indexOf(folder.key) == 0);
>>>>> var folderImages:XMLList = assetXML.image.(child('key').indexOf(folder.key) == 0);
>>>>> 
>>>>> Is now compiled as:
>>>>> 
>>>>> var /** @type {XMLList} */ folderFolders = this.assetXML.child('folder').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
>>>>> var /** @type {XMLList} */ folderImages = this.assetXML.child('image').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
>>>>> 
>>>>> “node.folder.key” is not correct. “folder” is a local variable of an un related object type.
>>>>> 
>>>>> I assume this broke with the recent XML filter changes.
>>>>> 
>>>>> Harbs
>>>>> 
>>>> 
>>>> 
>>>> 
>>> 
>>> 
>>> 
>> 
> 


Re: XML filters broke

Posted by Harbs <ha...@gmail.com>.
Well, it looks like I was wrong.

I just tested the following in Flash, and then both give the same results (i.e. return the attribute):

var emp = e.employee.(@id == 1).@name; // name of employee with id 1
var foo = e.employee.(1 == @id).@name; // name of employee with id 1

> On Aug 7, 2018, at 10:27 AM, Harbs <ha...@gmail.com> wrote:
> 
> Your example does not seem to be right to me.
> 
> Here’s the overview of how filters are supposed to work from the spec:
> 
>> Overview
>> When the left operand evaluates to an XML object, the filtering predicate adds the left operand to the front of the scope chain of the current execution context, evaluates the Expression with the augmented scope chain, converts the result to a Boolean value, then restores the scope chain. If the result is true, the filtering predicate returns an XMLList containing the left operand. Otherwise it returns an empty XMLList.
>> When the left operand is an XMLList, the filtering predicate is applied to each XML object in the XMLList in order using the XML object as the left operand and the Expression as the right operand. It concatenates the results and returns them as a single XMLList containing all the XML properties for which the result was true. For example,
>> 
>> var john = e.employee.(name == "John"); // employees with name John
>> var twoemployees = e.employee.(@id == 0 || @id == 1); // employees with id's 0 & 1
>> var emp = e.employee.(@id == 1).name; // name of employee with id 1
>> 
>> The effect of the filtering predicate is similar to SQL’s WHERE clause or XPath’s filtering predicates.
>> For example, the statement:
>> 
>> // get the two employees with ids 0 and 1 using a predicate
>> var twoEmployees = e..employee.(@id == 0 || @id == 1);
>> 
>> produces the same result as the following set of statements:
>> // get the two employees with the ids 0 and 1 using a for loop
>> var i = 0;
>> var twoEmployees = new XMLList();
>> for each (var p in e..employee) {
>>  with (p) {
>>    if (@id == 0 || @id == 1) {
>>      twoEmployees[i++] = p;
>>    }
>>  }
>> }
> 
> The question is what is "the front of the scope chain of the current execution context”? I’m pretty sure that means the start of sub-expressions. I don’t see how that can apply to the right-hand of comparison expressions. There is nothing in the spec about figuring out if a part of an expression is referring to XML or XMLList.
> 
>> On Aug 7, 2018, at 9:45 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>> 
>> I don't get what portion of the spec has to do with whether we append "node" to various expressions.  IMO, the changes I made only affect 6b.  6a is handled by generating a function with "node" as the parameter (because node is list[i] in the spec).  The task in 6b is to correctly evaluate any e4x filter expression.  I'm not sure what the limits are on what you can have in a filter expression, but if you can have just plain "@app" anywhere in the filter expression, I don't believe scoping rules would know to apply that to the "node" parameter without generating the "node" before "@app".
>> 
>> There is a chance that the Flex Compiler was using "magic" to generate the "node" and really should have reported an error.  I do remember being told that the filter function can be "anything".  Even:
>> (var foo:int = @app.length(); foo > @bar.length())  
>> 
>> If there are actual rules in the spec about evaluating the expression, that might apply to how we handle these expressions, otherwise I think the right thing is to resolve each expression and if the expression does not resolve to anything else, assume that it applies to the node.   I know the logic in EmitterUtils.writeE4xFilterNode isn't covering all cases.  It is trying to see what the expression resolves to, and returns false for known conditions (like a member of a class).  Just make it return false for your case (and feel free to add that case to the tests).  Eventually we'll have enough cases to either call it "good enough" or figure out a better way to determine when the expression applies to "node".
>> 
>> My 2 cents,
>> -Alex
>> 
>> On 8/6/18, 11:20 PM, "Harbs" <ha...@gmail.com> wrote:
>> 
>>   I just looked at the spec. I think it’s correct to append “node” to the first statement of the expression only. The only exception seems to be expressions which use boolean expressions (i.e. || or &&) in which case each piece of the boolean expression should be considered a self-contained expression. So in your example, there are really two filter expressions:
>>   1. hasOwnProperty("@app”)
>>   2. @app.length() > 0
>> 
>>   Both of those should have node appended to the front, but nothing else.
>> 
>>   Here’s the relevant semantics in the spec (the important bit being 6a):
>> 
>>> 6. For i = 0 to list.[[Length]]-1
>>> a. Add list[i] to the front of the scope chain
>>> b. Let ref be the result of evaluating Expression using the augmented scope chain of step 6a
>>> c. Let match = ToBoolean(GetValue(ref))
>>> d. Remove list[i] from the front of the scope chain
>>> e. If (match == true), call the [[Append]] method of r with argument list[i]
>>> 7. Return r
>> 
>>   Makes sense?
>> 
>>   Harbs
>> 
>>> On Aug 7, 2018, at 1:39 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>> 
>>> In porting Tour De Flex, there were patterns like this (explorerTree is XML):
>>> 
>>> explorerTree..node.(hasOwnProperty("@app") && @app.length() > 0)
>>> 
>>> The compiler logic before I made any changes yesterday just assumed that the first expression was a reference to the node parameter but other expressions were not, but it looks like the expression "@app.length()" was allowed in Flex as a reference to the node.  So I think the compiler has to determine what expressions evaluate to "nothing" which implies they are references to the node, and what did resolve to something.  This is all new logic and I don't know how to determine all of the test cases up front, so we'll have to keep tuning it as we find patterns that don't work as we want them to.
>>> 
>>> In your case, if the expression resolves to a VariableDefinition, that probably means that isn't a reference to node.  Not exactly sure, so you should debug into it to see what the node pattern is and return false.
>>> 
>>> Thanks,
>>> -Alex
>>> 
>>> On 8/6/18, 3:28 PM, "Harbs" <ha...@gmail.com> wrote:
>>> 
>>>  Doesn’t it always need to be a method for it to reference the node?
>>> 
>>>  I.e. child() should be node.child(), but foo.baz would not.
>>> 
>>>> On Aug 7, 2018, at 1:12 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>>> 
>>>> Yep, we need more intelligent understanding of when a reference is to the node or not.
>>>> 
>>>> Debug into EmitterUtils.writeE4xFilterNode and figure out the node pattern you need.
>>>> 
>>>> -Alex
>>>> 
>>>> On 8/6/18, 3:09 PM, "Harbs" <ha...@gmail.com> wrote:
>>>> 
>>>> var folderFolders:XMLList = assetXML.folder.(child('key').indexOf(folder.key) == 0);
>>>> var folderImages:XMLList = assetXML.image.(child('key').indexOf(folder.key) == 0);
>>>> 
>>>> Is now compiled as:
>>>> 
>>>> var /** @type {XMLList} */ folderFolders = this.assetXML.child('folder').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
>>>> var /** @type {XMLList} */ folderImages = this.assetXML.child('image').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
>>>> 
>>>> “node.folder.key” is not correct. “folder” is a local variable of an un related object type.
>>>> 
>>>> I assume this broke with the recent XML filter changes.
>>>> 
>>>> Harbs
>>>> 
>>> 
>>> 
>>> 
>> 
>> 
>> 
> 


Re: XML filters broke

Posted by Harbs <ha...@gmail.com>.
Your example does not seem to be right to me.

Here’s the overview of how filters are supposed to work from the spec:

> Overview
> When the left operand evaluates to an XML object, the filtering predicate adds the left operand to the front of the scope chain of the current execution context, evaluates the Expression with the augmented scope chain, converts the result to a Boolean value, then restores the scope chain. If the result is true, the filtering predicate returns an XMLList containing the left operand. Otherwise it returns an empty XMLList.
> When the left operand is an XMLList, the filtering predicate is applied to each XML object in the XMLList in order using the XML object as the left operand and the Expression as the right operand. It concatenates the results and returns them as a single XMLList containing all the XML properties for which the result was true. For example,
> 
> var john = e.employee.(name == "John"); // employees with name John
> var twoemployees = e.employee.(@id == 0 || @id == 1); // employees with id's 0 & 1
> var emp = e.employee.(@id == 1).name; // name of employee with id 1
> 
> The effect of the filtering predicate is similar to SQL’s WHERE clause or XPath’s filtering predicates.
> For example, the statement:
> 
> // get the two employees with ids 0 and 1 using a predicate
> var twoEmployees = e..employee.(@id == 0 || @id == 1);
> 
> produces the same result as the following set of statements:
> // get the two employees with the ids 0 and 1 using a for loop
> var i = 0;
> var twoEmployees = new XMLList();
> for each (var p in e..employee) {
>   with (p) {
>     if (@id == 0 || @id == 1) {
>       twoEmployees[i++] = p;
>     }
>   }
> }

The question is what is "the front of the scope chain of the current execution context”? I’m pretty sure that means the start of sub-expressions. I don’t see how that can apply to the right-hand of comparison expressions. There is nothing in the spec about figuring out if a part of an expression is referring to XML or XMLList.

> On Aug 7, 2018, at 9:45 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
> 
> I don't get what portion of the spec has to do with whether we append "node" to various expressions.  IMO, the changes I made only affect 6b.  6a is handled by generating a function with "node" as the parameter (because node is list[i] in the spec).  The task in 6b is to correctly evaluate any e4x filter expression.  I'm not sure what the limits are on what you can have in a filter expression, but if you can have just plain "@app" anywhere in the filter expression, I don't believe scoping rules would know to apply that to the "node" parameter without generating the "node" before "@app".
> 
> There is a chance that the Flex Compiler was using "magic" to generate the "node" and really should have reported an error.  I do remember being told that the filter function can be "anything".  Even:
> (var foo:int = @app.length(); foo > @bar.length())  
> 
> If there are actual rules in the spec about evaluating the expression, that might apply to how we handle these expressions, otherwise I think the right thing is to resolve each expression and if the expression does not resolve to anything else, assume that it applies to the node.   I know the logic in EmitterUtils.writeE4xFilterNode isn't covering all cases.  It is trying to see what the expression resolves to, and returns false for known conditions (like a member of a class).  Just make it return false for your case (and feel free to add that case to the tests).  Eventually we'll have enough cases to either call it "good enough" or figure out a better way to determine when the expression applies to "node".
> 
> My 2 cents,
> -Alex
> 
> On 8/6/18, 11:20 PM, "Harbs" <ha...@gmail.com> wrote:
> 
>    I just looked at the spec. I think it’s correct to append “node” to the first statement of the expression only. The only exception seems to be expressions which use boolean expressions (i.e. || or &&) in which case each piece of the boolean expression should be considered a self-contained expression. So in your example, there are really two filter expressions:
>    1. hasOwnProperty("@app”)
>    2. @app.length() > 0
> 
>    Both of those should have node appended to the front, but nothing else.
> 
>    Here’s the relevant semantics in the spec (the important bit being 6a):
> 
>> 6. For i = 0 to list.[[Length]]-1
>>  a. Add list[i] to the front of the scope chain
>>  b. Let ref be the result of evaluating Expression using the augmented scope chain of step 6a
>>  c. Let match = ToBoolean(GetValue(ref))
>>  d. Remove list[i] from the front of the scope chain
>>  e. If (match == true), call the [[Append]] method of r with argument list[i]
>> 7. Return r
> 
>    Makes sense?
> 
>    Harbs
> 
>> On Aug 7, 2018, at 1:39 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>> 
>> In porting Tour De Flex, there were patterns like this (explorerTree is XML):
>> 
>> explorerTree..node.(hasOwnProperty("@app") && @app.length() > 0)
>> 
>> The compiler logic before I made any changes yesterday just assumed that the first expression was a reference to the node parameter but other expressions were not, but it looks like the expression "@app.length()" was allowed in Flex as a reference to the node.  So I think the compiler has to determine what expressions evaluate to "nothing" which implies they are references to the node, and what did resolve to something.  This is all new logic and I don't know how to determine all of the test cases up front, so we'll have to keep tuning it as we find patterns that don't work as we want them to.
>> 
>> In your case, if the expression resolves to a VariableDefinition, that probably means that isn't a reference to node.  Not exactly sure, so you should debug into it to see what the node pattern is and return false.
>> 
>> Thanks,
>> -Alex
>> 
>> On 8/6/18, 3:28 PM, "Harbs" <ha...@gmail.com> wrote:
>> 
>>   Doesn’t it always need to be a method for it to reference the node?
>> 
>>   I.e. child() should be node.child(), but foo.baz would not.
>> 
>>> On Aug 7, 2018, at 1:12 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>>> 
>>> Yep, we need more intelligent understanding of when a reference is to the node or not.
>>> 
>>> Debug into EmitterUtils.writeE4xFilterNode and figure out the node pattern you need.
>>> 
>>> -Alex
>>> 
>>> On 8/6/18, 3:09 PM, "Harbs" <ha...@gmail.com> wrote:
>>> 
>>>  var folderFolders:XMLList = assetXML.folder.(child('key').indexOf(folder.key) == 0);
>>>  var folderImages:XMLList = assetXML.image.(child('key').indexOf(folder.key) == 0);
>>> 
>>>  Is now compiled as:
>>> 
>>>  var /** @type {XMLList} */ folderFolders = this.assetXML.child('folder').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
>>>  var /** @type {XMLList} */ folderImages = this.assetXML.child('image').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
>>> 
>>>  “node.folder.key” is not correct. “folder” is a local variable of an un related object type.
>>> 
>>>  I assume this broke with the recent XML filter changes.
>>> 
>>>  Harbs
>>> 
>> 
>> 
>> 
> 
> 
> 


Re: XML filters broke

Posted by Alex Harui <ah...@adobe.com.INVALID>.
I don't get what portion of the spec has to do with whether we append "node" to various expressions.  IMO, the changes I made only affect 6b.  6a is handled by generating a function with "node" as the parameter (because node is list[i] in the spec).  The task in 6b is to correctly evaluate any e4x filter expression.  I'm not sure what the limits are on what you can have in a filter expression, but if you can have just plain "@app" anywhere in the filter expression, I don't believe scoping rules would know to apply that to the "node" parameter without generating the "node" before "@app".

There is a chance that the Flex Compiler was using "magic" to generate the "node" and really should have reported an error.  I do remember being told that the filter function can be "anything".  Even:
(var foo:int = @app.length(); foo > @bar.length())  

If there are actual rules in the spec about evaluating the expression, that might apply to how we handle these expressions, otherwise I think the right thing is to resolve each expression and if the expression does not resolve to anything else, assume that it applies to the node.   I know the logic in EmitterUtils.writeE4xFilterNode isn't covering all cases.  It is trying to see what the expression resolves to, and returns false for known conditions (like a member of a class).  Just make it return false for your case (and feel free to add that case to the tests).  Eventually we'll have enough cases to either call it "good enough" or figure out a better way to determine when the expression applies to "node".

My 2 cents,
-Alex

On 8/6/18, 11:20 PM, "Harbs" <ha...@gmail.com> wrote:

    I just looked at the spec. I think it’s correct to append “node” to the first statement of the expression only. The only exception seems to be expressions which use boolean expressions (i.e. || or &&) in which case each piece of the boolean expression should be considered a self-contained expression. So in your example, there are really two filter expressions:
    1. hasOwnProperty("@app”)
    2. @app.length() > 0
    
    Both of those should have node appended to the front, but nothing else.
    
    Here’s the relevant semantics in the spec (the important bit being 6a):
    
    > 6. For i = 0 to list.[[Length]]-1
    >   a. Add list[i] to the front of the scope chain
    >   b. Let ref be the result of evaluating Expression using the augmented scope chain of step 6a
    >   c. Let match = ToBoolean(GetValue(ref))
    >   d. Remove list[i] from the front of the scope chain
    >   e. If (match == true), call the [[Append]] method of r with argument list[i]
    > 7. Return r
    
    Makes sense?
    
    Harbs
    
    > On Aug 7, 2018, at 1:39 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    > 
    > In porting Tour De Flex, there were patterns like this (explorerTree is XML):
    > 
    > explorerTree..node.(hasOwnProperty("@app") && @app.length() > 0)
    > 
    > The compiler logic before I made any changes yesterday just assumed that the first expression was a reference to the node parameter but other expressions were not, but it looks like the expression "@app.length()" was allowed in Flex as a reference to the node.  So I think the compiler has to determine what expressions evaluate to "nothing" which implies they are references to the node, and what did resolve to something.  This is all new logic and I don't know how to determine all of the test cases up front, so we'll have to keep tuning it as we find patterns that don't work as we want them to.
    > 
    > In your case, if the expression resolves to a VariableDefinition, that probably means that isn't a reference to node.  Not exactly sure, so you should debug into it to see what the node pattern is and return false.
    > 
    > Thanks,
    > -Alex
    > 
    > On 8/6/18, 3:28 PM, "Harbs" <ha...@gmail.com> wrote:
    > 
    >    Doesn’t it always need to be a method for it to reference the node?
    > 
    >    I.e. child() should be node.child(), but foo.baz would not.
    > 
    >> On Aug 7, 2018, at 1:12 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    >> 
    >> Yep, we need more intelligent understanding of when a reference is to the node or not.
    >> 
    >> Debug into EmitterUtils.writeE4xFilterNode and figure out the node pattern you need.
    >> 
    >> -Alex
    >> 
    >> On 8/6/18, 3:09 PM, "Harbs" <ha...@gmail.com> wrote:
    >> 
    >>   var folderFolders:XMLList = assetXML.folder.(child('key').indexOf(folder.key) == 0);
    >>   var folderImages:XMLList = assetXML.image.(child('key').indexOf(folder.key) == 0);
    >> 
    >>   Is now compiled as:
    >> 
    >>   var /** @type {XMLList} */ folderFolders = this.assetXML.child('folder').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
    >>   var /** @type {XMLList} */ folderImages = this.assetXML.child('image').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
    >> 
    >>   “node.folder.key” is not correct. “folder” is a local variable of an un related object type.
    >> 
    >>   I assume this broke with the recent XML filter changes.
    >> 
    >>   Harbs
    >> 
    > 
    > 
    > 
    
    


Re: XML filters broke

Posted by Harbs <ha...@gmail.com>.
I just looked at the spec. I think it’s correct to append “node” to the first statement of the expression only. The only exception seems to be expressions which use boolean expressions (i.e. || or &&) in which case each piece of the boolean expression should be considered a self-contained expression. So in your example, there are really two filter expressions:
1. hasOwnProperty("@app”)
2. @app.length() > 0

Both of those should have node appended to the front, but nothing else.

Here’s the relevant semantics in the spec (the important bit being 6a):

> 6. For i = 0 to list.[[Length]]-1
>   a. Add list[i] to the front of the scope chain
>   b. Let ref be the result of evaluating Expression using the augmented scope chain of step 6a
>   c. Let match = ToBoolean(GetValue(ref))
>   d. Remove list[i] from the front of the scope chain
>   e. If (match == true), call the [[Append]] method of r with argument list[i]
> 7. Return r

Makes sense?

Harbs

> On Aug 7, 2018, at 1:39 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
> 
> In porting Tour De Flex, there were patterns like this (explorerTree is XML):
> 
> explorerTree..node.(hasOwnProperty("@app") && @app.length() > 0)
> 
> The compiler logic before I made any changes yesterday just assumed that the first expression was a reference to the node parameter but other expressions were not, but it looks like the expression "@app.length()" was allowed in Flex as a reference to the node.  So I think the compiler has to determine what expressions evaluate to "nothing" which implies they are references to the node, and what did resolve to something.  This is all new logic and I don't know how to determine all of the test cases up front, so we'll have to keep tuning it as we find patterns that don't work as we want them to.
> 
> In your case, if the expression resolves to a VariableDefinition, that probably means that isn't a reference to node.  Not exactly sure, so you should debug into it to see what the node pattern is and return false.
> 
> Thanks,
> -Alex
> 
> On 8/6/18, 3:28 PM, "Harbs" <ha...@gmail.com> wrote:
> 
>    Doesn’t it always need to be a method for it to reference the node?
> 
>    I.e. child() should be node.child(), but foo.baz would not.
> 
>> On Aug 7, 2018, at 1:12 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
>> 
>> Yep, we need more intelligent understanding of when a reference is to the node or not.
>> 
>> Debug into EmitterUtils.writeE4xFilterNode and figure out the node pattern you need.
>> 
>> -Alex
>> 
>> On 8/6/18, 3:09 PM, "Harbs" <ha...@gmail.com> wrote:
>> 
>>   var folderFolders:XMLList = assetXML.folder.(child('key').indexOf(folder.key) == 0);
>>   var folderImages:XMLList = assetXML.image.(child('key').indexOf(folder.key) == 0);
>> 
>>   Is now compiled as:
>> 
>>   var /** @type {XMLList} */ folderFolders = this.assetXML.child('folder').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
>>   var /** @type {XMLList} */ folderImages = this.assetXML.child('image').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
>> 
>>   “node.folder.key” is not correct. “folder” is a local variable of an un related object type.
>> 
>>   I assume this broke with the recent XML filter changes.
>> 
>>   Harbs
>> 
> 
> 
> 


Re: XML filters broke

Posted by Alex Harui <ah...@adobe.com.INVALID>.
In porting Tour De Flex, there were patterns like this (explorerTree is XML):

explorerTree..node.(hasOwnProperty("@app") && @app.length() > 0)

The compiler logic before I made any changes yesterday just assumed that the first expression was a reference to the node parameter but other expressions were not, but it looks like the expression "@app.length()" was allowed in Flex as a reference to the node.  So I think the compiler has to determine what expressions evaluate to "nothing" which implies they are references to the node, and what did resolve to something.  This is all new logic and I don't know how to determine all of the test cases up front, so we'll have to keep tuning it as we find patterns that don't work as we want them to.

In your case, if the expression resolves to a VariableDefinition, that probably means that isn't a reference to node.  Not exactly sure, so you should debug into it to see what the node pattern is and return false.

Thanks,
-Alex

On 8/6/18, 3:28 PM, "Harbs" <ha...@gmail.com> wrote:

    Doesn’t it always need to be a method for it to reference the node?
    
    I.e. child() should be node.child(), but foo.baz would not.
    
    > On Aug 7, 2018, at 1:12 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
    > 
    > Yep, we need more intelligent understanding of when a reference is to the node or not.
    > 
    > Debug into EmitterUtils.writeE4xFilterNode and figure out the node pattern you need.
    > 
    > -Alex
    > 
    > On 8/6/18, 3:09 PM, "Harbs" <ha...@gmail.com> wrote:
    > 
    >    var folderFolders:XMLList = assetXML.folder.(child('key').indexOf(folder.key) == 0);
    >    var folderImages:XMLList = assetXML.image.(child('key').indexOf(folder.key) == 0);
    > 
    >    Is now compiled as:
    > 
    >    var /** @type {XMLList} */ folderFolders = this.assetXML.child('folder').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
    >    var /** @type {XMLList} */ folderImages = this.assetXML.child('image').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
    > 
    >    “node.folder.key” is not correct. “folder” is a local variable of an un related object type.
    > 
    >    I assume this broke with the recent XML filter changes.
    > 
    >    Harbs
    > 
    
    


Re: XML filters broke

Posted by Harbs <ha...@gmail.com>.
Doesn’t it always need to be a method for it to reference the node?

I.e. child() should be node.child(), but foo.baz would not.

> On Aug 7, 2018, at 1:12 AM, Alex Harui <ah...@adobe.com.INVALID> wrote:
> 
> Yep, we need more intelligent understanding of when a reference is to the node or not.
> 
> Debug into EmitterUtils.writeE4xFilterNode and figure out the node pattern you need.
> 
> -Alex
> 
> On 8/6/18, 3:09 PM, "Harbs" <ha...@gmail.com> wrote:
> 
>    var folderFolders:XMLList = assetXML.folder.(child('key').indexOf(folder.key) == 0);
>    var folderImages:XMLList = assetXML.image.(child('key').indexOf(folder.key) == 0);
> 
>    Is now compiled as:
> 
>    var /** @type {XMLList} */ folderFolders = this.assetXML.child('folder').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
>    var /** @type {XMLList} */ folderImages = this.assetXML.child('image').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
> 
>    “node.folder.key” is not correct. “folder” is a local variable of an un related object type.
> 
>    I assume this broke with the recent XML filter changes.
> 
>    Harbs
> 


Re: XML filters broke

Posted by Alex Harui <ah...@adobe.com.INVALID>.
Yep, we need more intelligent understanding of when a reference is to the node or not.

Debug into EmitterUtils.writeE4xFilterNode and figure out the node pattern you need.

-Alex

On 8/6/18, 3:09 PM, "Harbs" <ha...@gmail.com> wrote:

    var folderFolders:XMLList = assetXML.folder.(child('key').indexOf(folder.key) == 0);
    var folderImages:XMLList = assetXML.image.(child('key').indexOf(folder.key) == 0);
    
    Is now compiled as:
    
    var /** @type {XMLList} */ folderFolders = this.assetXML.child('folder').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
    var /** @type {XMLList} */ folderImages = this.assetXML.child('image').filter(function(node){return (node.child('key').indexOf(node.folder.key) == 0)});
    
    “node.folder.key” is not correct. “folder” is a local variable of an un related object type.
    
    I assume this broke with the recent XML filter changes.
    
    Harbs