Closed Bug 220362 Opened 21 years ago Closed 21 years ago

Local functions lose scope when called from outside (compiled with dynamic scopes, optlevel >= 0)

Categories

(Rhino Graveyard :: Core, defect)

x86
Linux
defect
Not set
normal

Tracking

(Not tracked)

VERIFIED FIXED

People

(Reporter: hannesw, Assigned: igor)

References

Details

Attachments

(2 files)

User-Agent:       Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030624
Build Identifier: 

When a local function is compiled with both dynamic scope and opt-level >= 0, it
only keeps its local scope as long as execution stays within that local scope.
Once execution leaves the local scope, the function loses it.

As soon as either compileFunctionsWithDynamicScope is set to false or the
optimization level is set to -1 on the Context, the function keeps the scope in
which it was defined.

The following script reproduces the problem (I'm also adding it as attachment)

// creates a local function and calls it immediately
function a() {
  var x = "A";
  var f = function() {
    java.lang.System.err.println(x);
  }
  f();
}

// creates and returns a local function
function b() {
  var x = "B";
  var f = function() {
    java.lang.System.err.println(x);
  }
  return f;
}


a(); // works
var f = b();
f(); // doesn't work

Reproducible: Always

Steps to Reproduce:
1.Run the attached script with optLevel >= 0 and
compileFunctionsWithDynamicScope = true.

Actual Results:  
A
js: "/home/hannes/cvs/adele/apps/antville/global/Aspects.js", line 14: uncaught
JavaScript exception: ReferenceError: "x" is not defined.
(/home/hannes/cvs/adele/apps/antville/global/Aspects.js; line 14)

Expected Results:  
A
B
Attached file testcase
reproduces the bug when compiled with dynamic scopes and opt-level >= 0.
The reason for the bug is that the optimizer did not check when appliing dynamic
scope if a function is a nested one or is under the with block as the
interpreter does. I will fix that.
Assignee: nboyd → igor
Testcase added to JS test suite:

      mozilla/js/tests/js1_5/Scope/regress-220362.js
The patch makes optimizer to behave in the same way as the interpreter does
with regard to dynamic scope: it ignores it for nested functions and functions
declared under with statements. Now parser checks for such functions and set
new flag itsIgnoreDynamicScope in FunctionNode. The flag then checked both by
interpreter and optimizer during byte code generation.

The patch also changes slightly interaction between changing dynamic scope flag
and interpreted Script instances. Currently the dynamic flag is read during
script execution but patch changes interpreter to behave exactly as the
optimizer does: the dynamic flag only affect script compilation, changes in its
value does not affect already compiled scripts.
I committed the fix.
Status: NEW → RESOLVED
Closed: 21 years ago
Resolution: --- → FIXED
Hannes, could you verify this bug for me? If it's fixed now, please
mark this bug as "Verified". If not, you can reopen it; thanks -
Thanks for the quick fix, and sorry for not testing it earlier (I'm in the
process of moving house).

My test-script is working correctly now in all settings, so the bug is fixed and
I'm marking it as verified. 

I noticed another problem, though. Local functions are now always compiled with
static local scope, which is right. However, the dynamic scope is completely
left out. I have variables set in the dynamic scope which script  writers expect
them to be there - and rightly so, since they shouldn't have to care about scope
imlementation internals. So I think the right layering of scopes in local
functions would be:

   local scope
   dynamic scope
   shared scope

Basically, the dynamic scope would have to be squeezed in between the local and
the shared scope. I don't know enough about dynamic scope implementation to be
able to tell how hard this would be to implement, but I'd be willing to dig into
it once I'm back in the office. 
Status: RESOLVED → VERIFIED
Regarding nested function scoping: are you sure that nested functions can not
access variables from denamic (or caller scope)? If so, do you have the same
behavior with interpreter and optimizer? A nested functions has the activation
object of its parent function as its scope and that activation object should
have the caller scope as its parent when dynamic scoping is on.

Note that compilation phase does not create any function instances, it just
translates JS source into either internal or JVM bytecode and makes it ready for
execution. Function instances are created during script execution and only at
this point scope comes into play.

I also curious why do you need to use dynamic scope at all? 


Nested function
Igor, sorry for my previous comment, and for not getting back to this earlier.
In fact, things are working correctly now. I must have mixed something up back
then. Thanks for the good work!
*** Bug 229244 has been marked as a duplicate of this bug. ***
Trageting as resolved against 1.5R5
Target Milestone: --- → 1.5R5
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: