You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cocoon.apache.org by Thorsten Scherler <th...@apache.org> on 2005/09/01 20:11:45 UTC

flow - evalFunc() broken in Rhino?

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

How can I solve this?

salu2
-- 
thorsten

"Together we stand, divided we fall!" 
Hey you (Pink Floyd)


Re: flow - evalFunc() broken in Rhino?

Posted by Thorsten Scherler <th...@apache.org>.
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)


Re: flow - evalFunc() broken in Rhino?

Posted by Jason Johnston <ja...@Intrado.com>.
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.