cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Thorsten Scherler <thors...@apache.org>
Subject Re: flow - evalFunc() broken in Rhino?
Date Thu, 01 Sep 2005 22:58:19 GMT
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)


Mime
View raw message