Re: How can I call variable in script like this global.var

Boris Zbarsky <[email protected]> Mon, 1 Apr 2019 17:06:16 -0400
Newsgroups gmane.comp.mozilla.devel.jseng
Message-ID <[email protected]>
Where to start...


On 4/1/19 4:19 PM, muhammad sami wrote:
>      RootedObject* document;
>      RootedObject* dialog;
>      RootedObject* anonymous;

You do know that RootedObject should only be used on the stack, right? 
Heap-allocating them is pretty much guaranteed to not work well in the 
end.  But that's not the immediate problem here...

>          JSString *str = rval.toString();
>          if (rval.isObject()) {

That toString() should really not happen until you know it's a string... 
  I strongly urge you to run this in debug mode, then fix all the 
resulting assertion failures.

>      bool changeScope() {
>          JS::HandleObject parent = JS::HandleObject::fromMarkedLocation(&document->get());
>          JS::MutableHandleObject protop = JS::MutableHandleObject::fromMarkedLocation(&document->get());

OK.  So both "parent" and "protop" are pointing to the same memory.

>          if (JS_GetPrototype(cx, parent, protop)) {

And therefore this overwrites "document" with its prototype.  After this 
point, "document" stores the thing that used to be its prototype 
(Object.prototype in the original "document" global, I would guess?

You should pretty much never create HandleObject or MutableHandleObject 
explicitly.  What this cod should have looked like, I suspect:

   RootedObject proto(cx);
   if (!JS_GetPrototype(cx, *document, &proto)) {
     // handle failure here
   }
   dialog = new RootedObject(cx, JS_NewObjectWithGivenProto(cx, 
&dialog_class, proto));

But none of that matters for the real issue at hand, because...

>              dialog = new RootedObject(cx, JS_NewObjectWithGivenProto(cx, &dialog_class, parentprotop));

OK, so this is creating a new object that is _not_ a global.

Then when you call run() and pass it "dialog" as globaloObj, and enter 
its compartment, you are actually entering the compartment of the global 
of "dialog", which is the compartment you were in when you called 
JS_NewObjectWithGivenProto, which is the compartment of "document".  So 
all the run() calls evaluate things at global scope, with the global 
being "document".

It sounds like you want to run things with a non-global "dialog" on the 
scope chain.  To do that, you need to use the version of JS::Evaluate 
that takes an AutoObjectVector scope chain.  See 
https://searchfox.org/mozilla-central/rev/09a322c117d64de4c652dd007daf515a13be1254/js/src/jsapi.h#3210-3216 
(though the line numbers may not match up in SpiderMonkey 45; I would 
check on that).

Hope that helps,
Boris