From dev-return-77618-apmail-cocoon-dev-archive=cocoon.apache.org@cocoon.apache.org Thu Sep 01 22:58:29 2005 Return-Path: Delivered-To: apmail-cocoon-dev-archive@www.apache.org Received: (qmail 27928 invoked from network); 1 Sep 2005 22:58:28 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 1 Sep 2005 22:58:28 -0000 Received: (qmail 83690 invoked by uid 500); 1 Sep 2005 22:58:25 -0000 Delivered-To: apmail-cocoon-dev-archive@cocoon.apache.org Received: (qmail 83639 invoked by uid 500); 1 Sep 2005 22:58:24 -0000 Mailing-List: contact dev-help@cocoon.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: dev@cocoon.apache.org List-Id: Delivered-To: mailing list dev@cocoon.apache.org Received: (qmail 83626 invoked by uid 99); 1 Sep 2005 22:58:24 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 01 Sep 2005 15:58:24 -0700 X-ASF-Spam-Status: No, hits=0.0 required=10.0 tests= X-Spam-Check-By: apache.org Received-SPF: neutral (asf.osuosl.org: local policy) Received: from [212.247.155.193] (HELO swip.net) (212.247.155.193) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 01 Sep 2005 15:58:39 -0700 X-T2-Posting-ID: R8gKnaFWehjcM2vTAiEuRA== Received: from [83.180.129.254] (HELO 192.168.2.4) by mailfe15.swip.net (CommuniGate Pro SMTP 4.3.4) with ESMTP id 14872445 for dev@cocoon.apache.org; Fri, 02 Sep 2005 00:58:20 +0200 Subject: Re: flow - evalFunc() broken in Rhino? From: Thorsten Scherler To: dev@cocoon.apache.org In-Reply-To: <1125603415.27210.25.camel@jjohnston> References: <1125598305.5300.58.camel@localhost.localdomain> <1125603415.27210.25.camel@jjohnston> Content-Type: text/plain Date: Fri, 02 Sep 2005 00:58:19 +0200 Message-Id: <1125615499.4859.32.camel@localhost.localdomain> Mime-Version: 1.0 X-Mailer: Evolution 2.0.2 Content-Transfer-Encoding: 7bit X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N On Thu, 2005-09-01 at 13:36 -0600, Jason Johnston wrote: > On Thu, 2005-09-01 at 20:11 +0200, Thorsten Scherler wrote: > > Hi all, > > > > I have a problem with the evalFunc() in flow. I think that not only the > > eval() function is broken, but as well the evalFunc(). > > > > Add the following to your flow script: > > > > var genericDoc; > > scriptString= "genericDoc='testing';"; > > evalFunc = new Function ("genericDoc",scriptString); > > evalFunc(genericDoc); > > print("xxx ",genericDoc); > > > > The sysout gives you: > > xxx undefined > > > > That is not what the following link says (thx again Jason Johnston, for > > this awesome link): > > http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Function#Created_By > > "However, if you pass an object as a parameter to a function and the > > function changes the object's properties, that change is visible outside > > the function." > > Your code is actually not "changing the object's properties". If you > were to try genericDoc.property='value' then that would work since > you're changing a property of the object referred to by the genericDoc > variable. However your code is actually changing which object > genericDoc refers to, which is not the same thing. Remember, variables > are not objects but *pointers to* objects. > > Now, you might expect that changing genericDoc's value inside the > function would also change the value of the genericDoc variable from > outside the function. But this is not the case in your example because > function arguments are treated as variables local to the function, so > the genericDoc variable (the named argument) inside the function is > different than the genericDoc variable outside the function. > > If you want genericDoc within the function to be the same variable as > genericDoc outside, you can rely on closures. This basically means that > when a function is created (as happens with new Function("")) it creates > a closure so that the code within the function has access to the entire > scope of where it was created. So: > > var genericDoc; > scriptString= "genericDoc='testing';"; > evalFunc = new Function (scriptString); > evalFunc(); > print("xxx ",genericDoc); > > ...should work, since evalFunc automatically gets access to the > genericDoc variable since it was in scope when evalFunc was created. > > Hope this makes at least a little sense. It's taken me a long while to > get a handle on the complexity of closures. :) Thanks for this comprehensive explanation, yes that makes a lot of sense (after reading it a couple of times). ;-) The only thing is the scope that does not seem to work, like you described, but using the properties is working. :) The only important thing is that the var is initialized (like "var genericDoc={doc:null};") otherwise (for "var genericDoc;") you get "The undefined value has no properties.". Here is the roundtrip that I did. Thanks again Jason, you have been a great help. 1) I tried: var genericDoc="doh!"; print('before ',genericDoc); var evalFunc = new Function ("print('/testing',genericDoc)"); evalFunc(); print("xxx ",genericDoc); It gives: sysout: before doh! cocoon: org.mozilla.javascript.EcmaError: "genericDoc" is not defined. 2) Now changing the code to: var genericDoc="doh!"; print('before ',genericDoc); var evalFunc = new Function ("genericDoc","print('/testing',genericDoc)"); evalFunc(genericDoc); print("xxx ",genericDoc); It gives (sysout): before doh! /testing doh! xxx doh! 3) Changing it to: var genericDoc="doh!"; print('before ',genericDoc); var evalFunc = new Function ("genericDoc","genericDoc='working'"); evalFunc(genericDoc); print("xxx ",genericDoc); Gives (sysout): before doh! xxx doh! 4) Changing it to: var genericDoc="doh!"; print('before ',genericDoc); var evalFunc = new Function ("genericDoc='working'"); evalFunc(); print("xxx ",genericDoc); gives: sysout: before doh! cocoon: java.lang.ClassCastException 5) Changing: var genericDoc={value:"doh!"}; print('before ',genericDoc.value); var evalFunc = new Function ("genericDoc.value='working'"); evalFunc(); print("xxx ",genericDoc.value); gives: sysout: before doh! cocoon: org.mozilla.javascript.EcmaError: "genericDoc" is not defined. 6) Changing: var genericDoc={value:"doh!"}; print('before ',genericDoc.value); var evalFunc = new Function ("genericDoc","genericDoc.value='working'"); evalFunc(genericDoc); print("xxx ",genericDoc.value); gives (sysout): before doh! xxx working salu2 -- thorsten "Together we stand, divided we fall!" Hey you (Pink Floyd)