how to call the javascript methods from v8?

95 views
Skip to first unread message

swathi jakkam

unread,
Apr 12, 2012, 12:52:37 AM4/12/12
to v8-users
Hi,

how to call the javascript methods from v8?
i wrote one function in javascript.I want call that function from
v8.could you please give the solution.

for example:I wrote the code in js file below:

function JS_fun(num) {
var JS_Dial = {};

JS_Dial.fun_name = "sum";
JS_Dial.phonenum = num;

var JSON_Str = JSON.stringify(JS_Dial);
print(JSON_Str);

}

here JS_fun() is implemented in javascript.i need how call this
JS_fun() from v8.


some one said
---------------------
Depends on how do you get a function, you can get it from an argument
then
it would be:
v8::Local<v8::Value> func = args[x];

I think there is a way to get it from Global context too.

and if you have a function object you call it like that:
v8::Persistent<v8::Function> func =
v8::Persistent<v8::Function>::Cast(obj);

v8::Handle<v8::Value> returnObj =
func->Call(v8::Context::GetCurrent()->Global(),
<argcount>, <args>);


but, i am not getting clearly. Could you please Explain clearly.
could you write any sample example for accessing java script function.


Regards,
swathi.

Mike Schwartz

unread,
Apr 12, 2012, 7:32:39 AM4/12/12
to v8-u...@googlegroups.com
// this C++ function is callable from JS
Handle<Value>myFunction(Argments& args) {
  v8::Local<v8::Value> func = args[x];
  v8::Persistent<v8::Function> func =
  v8::Persistent<v8::Function>::Cast(obj);

  v8::Handle<v8::Value> returnObj =
  func->Call(v8::Context::GetCurrent()->Global(),
                       <argcount>, <args>);
  return Undefined();
}

In your main code, you make it accessible to JavaScript:
globalObject->Set("myFunction", FunctionTemplate::New(myFunction));

You set the globalObject when you create your context.

The JavaScript code can do:
myFunc(JS_fun);

If you'd like to see a straightforward use of v8, you might look at my project:

Cheers

Stephan Beal

unread,
Apr 12, 2012, 7:45:53 AM4/12/12
to v8-u...@googlegroups.com
On Thu, Apr 12, 2012 at 1:32 PM, Mike Schwartz <myk...@gmail.com> wrote:
// this C++ function is callable from JS
  v8::Persistent<v8::Function>::Cast(obj);

Out of curiosity: why do you use Persistent there? i've never used Persistent for a local-scope handle before.

@OP: be very aware that Cast() will CRASH your app if obj is-not-a Function, so check arg.IsObject() first.

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

Michael Schwartz

unread,
Apr 12, 2012, 9:24:56 AM4/12/12
to v8-u...@googlegroups.com
D'oh

I just copied/pasted someone else's previous example in the thread.

Yes, Local<Handle> is the right way.

As far as the crash goes...

If you check out the silkjs repository, you'll see I do near zero error checking in the C++ code.  So it does crash, just like a C/C++ program will if you pass garbage to an OS call (for example).

However, you can do something like this (which silkjs does do).   Wrap the calls to C++ with JavaScript that does the error checking before calling the C++ function.

IMO, it makes the API a lot cleaner.  The C++ code might return false on failure, but your JavaScript API built on top of the C++ might want to throw an exception.  The throwing of exceptions being YOUR API's method of choice of handling errors.  Someone else's API might want to return true/false to indicate success.

Cheers



Stephan Beal

unread,
Apr 12, 2012, 9:31:49 AM4/12/12
to v8-u...@googlegroups.com
On Thu, Apr 12, 2012 at 3:24 PM, Michael Schwartz <myk...@gmail.com> wrote:
If you check out the silkjs repository, you'll see I do near zero error checking in the C++ code.  So it does crash, just like a C/C++ program will if you pass garbage to an OS call (for example).

Sorry, i didn't mean to imply that that was explicitly an error, only that leaving out the IsObject() check "might severely shorten the app's lifetime."
 
However, you can do something like this (which silkjs does do).   Wrap the calls to C++ with JavaScript that does the error checking before calling the C++ function.

That's a fine solution. Nowadays i mostly use C++ templates which validate the args and dispatch to an appropriate native overload:


Happy Hacking!

Michael Schwartz

unread,
Apr 12, 2012, 9:39:32 AM4/12/12
to v8-u...@googlegroups.com
Nice.  I've seen v8-juice many times.

In my case, I really coded for speed.  It got to the point in HTTP serving where an extra syscall or string copy was killing my requests/second performance by 10%.  That's like from 45,000 requests/second down to 40,000.

I'm even questioning whether I even need HandleScope at all.  Every nanosecond counts! ;-)


Stephan Beal

unread,
Apr 12, 2012, 9:43:37 AM4/12/12
to v8-u...@googlegroups.com
On Thu, Apr 12, 2012 at 3:39 PM, Michael Schwartz <myk...@gmail.com> wrote:
In my case, I really coded for speed.  It got to the point in HTTP serving where an extra syscall or string copy was killing my requests/second performance by 10%.  That's like from 45,000 requests/second down to 40,000.

Obviously, my approach (lazy/convenient) is not appropriate there :).

I'm even questioning whether I even need HandleScope at all.  Every nanosecond counts! ;-)

i gave up handle scopes a long time ago - 99% of my code is called "from v8", so i've never needed them. i didn't give them up for performance, but because i just kept seeing weird crashes very often which went away when i removed the handle scopes. So my vote is: don't feel bad about getting rid of them. Funcs called "from v8" implicitly have a scope. Only funcs which use v8 and are called from native code (possibly) need a handle scope. At least that's my understanding based on past threads on this list.

Michael Schwartz

unread,
Apr 12, 2012, 9:55:05 AM4/12/12
to v8-u...@googlegroups.com
Thanks for the tip.

Check this out:


It works, but the child process doesn't have the debugger or tick threads running anymore.  Any idea how to get those running again?

Stephan Beal

unread,
Apr 12, 2012, 9:59:41 AM4/12/12
to v8-u...@googlegroups.com
On Thu, Apr 12, 2012 at 3:55 PM, Michael Schwartz <myk...@gmail.com> wrote:

It works, but the child process doesn't have the debugger or tick threads running anymore.  Any idea how to get those running again?

Unfortunately, no. i implemented fork() for the SpiderMonkey engine back in 2007, but that was threadless and in C, so i never had any significant problems with it (other than having absolutely no idea whether or not the JS VM reacted properly after forking).

But in any case:

HandleScope scope;
return scope.Close(Integer::New(pid));

That scope isn't necessary - your fork() is already being called from v8 and has an implicit scope.

Stephan Beal

unread,
Apr 12, 2012, 10:02:37 AM4/12/12
to v8-u...@googlegroups.com
On Thu, Apr 12, 2012 at 3:59 PM, Stephan Beal <sgb...@googlemail.com> wrote:
On Thu, Apr 12, 2012 at 3:55 PM, Michael Schwartz <myk...@gmail.com> wrote:

One potential improvement: change it to take a function and fork that function as the child process. That simplifies how fork() is called, in my experience, but i honestly have no idea if the v8 internals would behave properly in that case.

Michael Schwartz

unread,
Apr 12, 2012, 10:10:46 AM4/12/12
to v8-u...@googlegroups.com
My thinking is that I'm lucky enough that fork() clones the V8 context as-is.

Again, using the JavaScript overload technique:

var old_fork = process.fork;
process.fork = function(childMethod) {
  if (old_fork()) return;
  childMethod();
  process.exit();
}

;-)

And yeah, I'm going to excise the HandleScope everywhere in the builtin API.  It's not been causing errors, but I'm sure it'd save some clock cycles.



Paul Harris

unread,
Apr 23, 2012, 7:03:20 PM4/23/12
to v8-u...@googlegroups.com
Hello,

I'm new, so can someone please check my logic here...

So if I understand correctly:

* there is no real difference between Local<> and Handle<>, both need a HandleScope.  Local<> does not clean up after itself like a smartpointer.

* the reason that you may not need a HandleScope is if the function caller (or its caller, etc etc) has already created a HandleScope.

and:
* if you do NOT make a HandleScope, then any objects that you created in your function will not be released until much later.
so for example, if your function is called by v8 like so:

void some_v8_core_function()
{
   HandleScope scope;
   vector<> handles;
   for (int i = 0; i < a billion; ++i)
      handles.push_back(your_function(whatever));
  // v8 keeps the handles it got from your_function
}

then your function's handles won't be cleaned up until after the loop has run a billion times.  So if your_function looks like this:

void your_function( v8::Args whatever )
{
  // note - no handlescope
   Local<Value> val = v8::String::New(whatnot);
   // do stuff
   return v8::Number::New(something);
}

then there will be a billion strings created and NOT released until the loop has finished.
the Numbers will be eventually kept by v8 to do things, but the Strings will all be cleaned up.

So the difference is,
* with handlescope in your_function(): cleans up (ie release) along the way,
* without handlescope in your_function: does not release until an assumed scope further up the call chain is closed.

And we have no real way of knowing how v8 is calling our functions.
Are they always wrapping calls to our functions with HandleScope?  without looking at the code, I'd say no, as there would be a performance penalty for being cautious.


Is that how things work?

cheers
Paul

Reply all
Reply to author
Forward
0 new messages