I am trying to access a variable value in the current scope chain:
function foo() {
var myVar = 123;
function bar() {
Print( EvalVarByName('myVar') );
};
bar();
};
foo();
EvalVarByName native function is define as:
...
JSStackFrame *fp = JS_GetScriptedCaller(cx, NULL);
JSBool found;
JSObject *scope = JS_GetFrameScopeChain(cx, fp);
for ( ; scope; scope = JS_GetParent(cx, scope) ) {
JS_HasProperty(cx, scope, name, &found);
if ( found )
return JS_GetProperty(cx, scope, name, rval);
}
...
(src: http://code.google.com/p/jslibs/source/browse/trunk/src/tools/jsTest.cpp?spec=svn2940&r=2940#1)
note1: if I remove the outer function foo, EvalVarByName('myVar')
returns 123.
note2: using JS_GetScopeChain(cx) give the same result.
Is there a better method to access myVar without using eval-like
functions ?
Franck.
That suggests that your code works for the global scope but fails for
the closure.
If you add a dummy EvalVarByName JS function, put the code in to
Firebug, and set a breakpoint in EvalVarByName you can look at the
scopes in the Watch side panel.
jjb
Oh, I understand my mistake.
I have to search in the scope chain of the caller of EvalVarByName,
not EvalVarByName itself.
Thanks.
Franck.
I see what's happening here. You're running into a JS optimization.
The debugger APIs can detect some optimizations that are otherwise
transparent. Here the JS compiler sees that bar does not actually close
on any local variables in foo, so its scope chain does not include foo's
locals. Only the debugger APIs can tell the difference.
If the function did actually use myVar, that part of the scope chain
would be retained.
> Is there a better method to access myVar without using eval-like
> functions ?
I don't think so. What are you trying to do?
Later, you wrote:
> Oh, I understand my mistake.
> I have to search in the scope chain of the caller of EvalVarByName,
> not EvalVarByName itself.
Alas, I think this comment is mistaken. JS_GetScriptedCaller already
skips the (non-scripted) stack frame of EvalVarByName itself. Try this:
function foo() {
var myVar = 123;
return function bar() {
Print( EvalVarByName('myVar') );
};
}
var bar = foo();
bar();
I don't think this will work for you.
-j
> > Is there a better method to access myVar without using eval-like
> > functions ?
>
> I don't think so. What are you trying to do?
>
I try to enable my Expand() function to use the scope chain. eg:
var a = 'a';
function foo() {
var b = 'b';
function bar() {
var c = 'c';
Print( Expand('$(a)$(b)$(c)') );
};
bar();
};
foo();
Franck.
JSStackFrame *fp = JS_GetScriptedCaller(cx, NULL);
for ( JSObject *scope = JS_GetFrameScopeChain(cx, fp); scope; scope =
JS_GetParent(cx, scope) ) {
JS_HasProperty(cx, scope, name, &found);
if ( found ) {
JS_GetProperty(cx, scope, name, vp);
return JS_TRUE;
}
}
Franck.
I have recently moved to JS 1.8rc1 from JS 1.5. Thanks to SM, for
maintaining its backward compatibility for such a long time.
But, now JS 1.8 is reporting out of memory for same scenarios which
were used to be OK for JS 1.5.
I am using spidermonkey API's in below sequence:
1. JS_NewRuntime(1 << 14); maxbytes : 1 << 14 bytes
2. JS_NewContext(rt, 1<<13)
3. JS_NewObject() : Create class object
4. JS_InitStandardClasses
I debugged this issue and got to know that JS 1.8 is reporting "out of
memory" in InitStandardClasses API. To get rid of this, I tried increasing
size of runtime, so it didn't work with "1<<15", but got initialized with
1<<16.
Memory required for initialization in JS 1.8 is about 4 times the size of
JS 1.5 took. Or these is something which I need do along with current set of
API. Or it has something to do with Garbage collector. I tried using
JS_GetGCParameter API, but it also specifies same values which JS_NewRuntime
specifies.
Now, memory requirement has increased subsequently, is there any way to
curb this memory consumption which is getting huge in initialization itself.
Regards,
Puneet
Franck, this is hopeless. The JS engine is not going to keep around
apparently-dead variables on the off chance that someone might call a
native function that uses the debugger APIs to read them off the stack.
The debugger APIs don't work that way. You can use eval:
var a = 'a';
function foo() {
var b = 'b';
function bar() {
var c = 'c';
Print(eval(Expand('$(a)$(b)$(c)')));
}
bar();
}
foo();
where Expand('$(a)$(b)$(c)') returns the string '""+(a)+(b)+(c)'.
Or you can run your JS code through the C preprocessor before passing it
to SpiderMonkey, and use something like
#define Expand(s) eval(__expand(s))
-j