Adding property to global object, that points to global object

1,888 views
Skip to first unread message

Aaron C

unread,
Jan 23, 2011, 1:55:11 PM1/23/11
to v8-users
Outside of the browser (and in a stand alone project that references
the V8.lib), I'm trying to load and compile some JavaScript code which
contains a few references to various Browser DOM related objects. As I
don't actually need to fully execute the code (as the intention is to
perform some code analysis), I'd like to translate the following
JavaScript into C++ code for use with the V8 API.

this.window = this;
this.navigator = {
userAgent : "MSIE"
};
this.document = {
documentElement : {}
};

I just haven't been able to get my head around the API. I have a work
around (which is to simply execute the code above directly as
JavaScript), although I'd really appreciate someone helping me how to
properly add the equivalent code in C++.

I'm using the shell.cc as the starter for my code parser. I've tried
various combinations of GetPrototype, etc., but can't seem to get the
reference to the global object working properly.

This, for example, throws an exception:

global->Set(String::New("window"), global);

I assume it's too early (as I put it before the Context::New). But,
when I move it after the context is created with the global object,
the window property isn't set.

This JavaScript code will fail (with window type is undefined).

if (!window) this.window = this;

(Since the JavaScript code isn't mine, I'd rather not fix it just so
that it compiles).

Thanks!

Stephan Beal

unread,
Jan 23, 2011, 2:11:34 PM1/23/11
to v8-u...@googlegroups.com
On Sun, Jan 23, 2011 at 7:55 PM, Aaron C <co...@wiredprairie.us> wrote:
this.navigator = {
 userAgent : "MSIE"
};
this.document = {
       documentElement : {}
};


Maybe something like...

a) Create a new Object:

Local<Object> obj( Object::New() );

b) Add that object to the global object:

Local<Object> global( v8::Context::GetCurrent()->Global() );

global->Set( String::New("document"), obj );

now your global object has a plain object called 'document'. You would repeat this for the navigator item, and insert the userAgent and documentElements as children of the navigator/document.

Or, even easier:

Since you're using the sample shell, you have the load() function: simply write the above JS code into a file, and load() that file before proceeding with the other scripts.

 

This, for example, throws an exception:

   global->Set(String::New("window"), global);

That should work just fine - i do that same thing in some code to give my global object a name.
 
   if (!window) this.window = this;

You can do this to avoid that error:

if( 'undefined' === typeof this.window ) this.window = this;
 

--
----- stephan beal
http://wanderinghorse.net/home/stephan/

Aaron C

unread,
Jan 24, 2011, 8:44:37 AM1/24/11
to v8-users
Hi, I'm interested in learning how to get the window object map to the
"global" object in particular correctly. As I said, I can't edit the
JavaScript file being loaded (as it's not mine and I didn't mention
that it's also in source control and this code would be part of a
build/verification tool, and I'm sure that it would be a slippery
slope of one tiny fix after another). And although I could pre-load a
JavaScript file with 'fixes" as I also had mentioned, I'd like to
learn how to do this in C++ first, before I resort to a JavaScript
solution.

I've continued to explore and believe I've gotten closer to a working
solution. I'm not sure if it's correct, but the JavaScript code now
loads. :)

Handle<Object> v8RealGlobal = Handle<Object>::Cast(context->Global()-
>GetPrototype());

Context::Scope context_scope(context);

Local<ObjectTemplate> docTmpl = ObjectTemplate::New();
docTmpl->SetNamedPropertyHandler(MapGet, MapSet);
Local<Object> docObj = docTmpl->NewInstance();

v8RealGlobal->Set(String::New("document"), docObj);

// this appears to work -- grab the prototype from the context global
and assign it to the global variable named "window"
v8RealGlobal->Set(String::New("window"), v8RealGlobal);

The code then loads the scripts.

And then very simple MapGet/Set functions:

Handle<Value> MapGet(Local<String> name, const AccessorInfo& info) {
return Object::New();
}

Handle<Value> MapSet(Local<String> name,
Local<Value> value_obj,
const AccessorInfo& info)
{
return value_obj;
}

Thanks!

--Aaron
http://www.wiredprairie.us

Anton Muhin

unread,
Jan 24, 2011, 10:33:29 AM1/24/11
to v8-u...@googlegroups.com
Aaron,

your code seems reasonable enough.

v8 splits global object into two parts: so named global proxy (one
which you obtain with the Global()) and 'real' global---object on
which properties can be set, etc. The reason is browser security.

yours,
anton.

> --
> v8-users mailing list
> v8-u...@googlegroups.com
> http://groups.google.com/group/v8-users
>

Reply all
Reply to author
Forward
0 new messages