No, the problem is not with the C++ functions registered to JS before the script->Run() call. The problem occurs when, "during the JS run", the JS program calls a C++ function which in turn tries to register new functions via global->set.
Actually what I am trying to do is create a function
called import that, as python's import, makes new
modules available to the running script.
I attached the files. The javascript program starts with
a call to import("./rename.so"); which calls a function
named "ImportJSModule" in the v8js.cc program.
This function uses dlopen to dynamically link rename.so
(which came, obviously, from rename.cc), then it calls
a function named startup which tells ImportJSModule
that it has the symbol "rename". So, ImportJSModule
call dlsym to get a pointer to it. Then, ImportJSModule
calls global->set to register "rename" and make it
available to the javascript program. There's no error
until there. But, when the javascript program tries to
call "rename", it gets the ReferenceError message.
That's the problem.
Thank you
Luis Otavio de Colla Furquim
On Wed, Jun 3, 2009 at 7:18 PM, Dennis Honeyman <[email protected]> wrote:
>
> Umm, I think you need to put the global->Set(...) before creating the
> context and entering the context scope...
>
> ---
> v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
> global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print));
> v8::Handle<v8::Context> context = v8::Context::New(NULL, global);
> v8::Context::Scope context_scope(context);
> ---
>
> I think that'll work, provided you use the proper format for the function...
>
> >
>
--
Luis Otavio de Colla Furquim
Não alimente os pingos
Don't feed the tribbles - http://www.thinkgeek.com/geektoys/plush/ac6e/
By the nice edges of dataly graphs I shall walk
http://www.furquim.org/chironfs/
--~--~---------~--~----~------------~-------~--~----~
v8-users mailing list
[email protected]
http://groups.google.com/group/v8-users
-~----------~----~----~----~------~----~------~--~---
// Copyright 2008 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <v8/v8.h>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <dlfcn.h>
//#include <string>
#include <unordered_map>
#include <regex>
void RunShell(v8::Handle<v8::Context> context);
bool ExecuteString(v8::Handle<v8::String> source,
v8::Handle<v8::Value> name,
bool print_result,
bool report_exceptions);
v8::Handle<v8::Value> Print(const v8::Arguments& args);
v8::Handle<v8::Value> Load(const v8::Arguments& args);
v8::Handle<v8::Value> Quit(const v8::Arguments& args);
v8::Handle<v8::Value> Version(const v8::Arguments& args);
v8::Handle<v8::String> ReadFile(const char* name);
void ReportException(v8::TryCatch* handler);
typedef char ** (*ini_func)();
typedef v8::Handle<v8::Value> (*jsfn)(const v8::Arguments& args);
v8::HandleScope handle_scope;
// Create a template for the global object.
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
v8::Handle<v8::Context> context = v8::Context::New(NULL, global);
v8::Context::Scope context_scope(context);
char* ToString(v8::Handle<v8::String> obj)
{
int length = obj->Length();
char* buf = new char[length];
obj->Write(reinterpret_cast<uint16_t*>(buf), 0, length);
return buf;
}
std::unordered_map<char *, void *> ImportJSModule_modHandle;
v8::Handle<v8::Value> ImportJSModule(const v8::Arguments& args)
{
char **s;
void *modHandle;
jsfn symHandle;
ini_func initialize;
// v8::Context::Scope context_scope(context);
v8::String::Utf8Value str(args[0]);
if (ImportJSModule_modHandle.find(*str)==ImportJSModule_modHandle.end()) {
printf("%s\n",*str);
modHandle = dlopen(*str, RTLD_NOW);
printf("a\n");
fflush(stdout);
if ( modHandle == 0 ) {
printf("%s\n",dlerror());
ThrowException(v8::String::New("library cant be opened\n"));
} else {
printf("b\n");
fflush(stdout);
initialize = (ini_func) dlsym (modHandle, "startup");
printf("c\n");
fflush(stdout);
if (initialize==0) {
printf("%s\n",dlerror());
fflush(stdout);
} else {
printf("c.1\n");
fflush(stdout);
for(s=initialize();(*s)!=NULL;s++) {
symHandle = (jsfn) dlsym (modHandle, *s);
if (symHandle==0) {
ThrowException(v8::String::New("library loaded, but symbol not loaded\n"));
} else {
printf("sym: %s\n",*s);
fflush(stdout);
global->Set(v8::String::New(*s), v8::FunctionTemplate::New(symHandle)); // add Line to JS
printf("again: %s\n",*s);
fflush(stdout);
}
}
printf("d\n");
fflush(stdout);
ImportJSModule_modHandle[*str] = modHandle;
}
printf("e\n");
fflush(stdout);
}
} else {
ThrowException(v8::String::New("Module already loaded\n"));
}
return v8::Undefined();
};
v8::Handle<v8::Value> UnloadJSModule(const v8::Arguments& args)
{
std::unordered_map<char *, void *>::iterator iter;
v8::String::Utf8Value str(args[0]);
if ((iter=ImportJSModule_modHandle.find(*str))==ImportJSModule_modHandle.end()) {
ThrowException(v8::String::New("Module not loaded\n"));
} else {
dlclose(iter->second);
ImportJSModule_modHandle.erase(iter);
}
return v8::Undefined();
};
int main(int argc, char* argv[])
{
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
global->Set(v8::String::New("import"), v8::FunctionTemplate::New(ImportJSModule)); // add Line to JS
// Bind the global 'print' function to the C++ Print callback.
global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print));
// Bind the global 'load' function to the C++ Load callback.
global->Set(v8::String::New("load"), v8::FunctionTemplate::New(Load));
// Bind the 'quit' function
global->Set(v8::String::New("quit"), v8::FunctionTemplate::New(Quit));
// Bind the 'version' function
global->Set(v8::String::New("version"), v8::FunctionTemplate::New(Version));
// Create a new execution environment containing the built-in
// functions
// Point s = Point();
//templatePoint->ExposeObject(global, &s, "s", false);
// v8::Handle<v8::Context> context = v8::Context::New(NULL, global);
// Enter the newly created execution environment.
// v8::Context::Scope context_scope(context);
context = v8::Context::New(NULL, global);
// Enter the newly created execution environment.
v8::Context::Scope context_scope(context);
bool run_shell = (argc == 1);
for (int i = 1; i < argc; i++) {
const char* str = argv[i];
if (strcmp(str, "--shell") == 0) {
run_shell = true;
} else if (strcmp(str, "-f") == 0) {
// Ignore any -f flags for compatibility with the other stand-
// alone JavaScript engines.
continue;
} else if (strncmp(str, "--", 2) == 0) {
printf("Warning: unknown flag %s.\n", str);
} else if (strcmp(str, "-e") == 0 && i + 1 < argc) {
// Execute argument given to -e option directly
v8::HandleScope handle_scope;
v8::Handle<v8::String> file_name = v8::String::New("unnamed");
v8::Handle<v8::String> source = v8::String::New(argv[i + 1]);
if (!ExecuteString(source, file_name, false, true))
return 1;
i++;
} else {
// Use all other arguments as names of files to load and run.
v8::HandleScope handle_scope;
v8::Handle<v8::String> file_name = v8::String::New(str);
v8::Handle<v8::String> source = ReadFile(str);
if (source.IsEmpty()) {
printf("Error reading '%s'\n", str);
return 1;
}
if (!ExecuteString(source, file_name, false, true))
return 1;
}
}
// if (run_shell) RunShell(context);
return 0;
}
// The callback that is invoked by v8 whenever the JavaScript 'print'
// function is called. Prints its arguments on stdout separated by
// spaces and ending with a newline.
v8::Handle<v8::Value> Print(const v8::Arguments& args) {
bool first = true;
for (int i = 0; i < args.Length(); i++) {
v8::HandleScope handle_scope;
if (first) {
first = false;
} else {
printf(" ");
}
v8::String::Utf8Value str(args[i]);
printf("%s", *str);
}
printf("\n");
return v8::Undefined();
}
// The callback that is invoked by v8 whenever the JavaScript 'load'
// function is called. Loads, compiles and executes its argument
// JavaScript file.
v8::Handle<v8::Value> Load(const v8::Arguments& args) {
for (int i = 0; i < args.Length(); i++) {
v8::HandleScope handle_scope;
v8::String::Utf8Value file(args[i]);
v8::Handle<v8::String> source = ReadFile(*file);
if (source.IsEmpty()) {
return v8::ThrowException(v8::String::New("Error loading file"));
}
if (!ExecuteString(source, v8::String::New(*file), false, false)) {
return v8::ThrowException(v8::String::New("Error executing file"));
}
}
return v8::Undefined();
}
// The callback that is invoked by v8 whenever the JavaScript 'quit'
// function is called. Quits.
v8::Handle<v8::Value> Quit(const v8::Arguments& args) {
// If not arguments are given args[0] will yield undefined which
// converts to the integer value 0.
int exit_code = args[0]->Int32Value();
exit(exit_code);
return v8::Undefined();
}
v8::Handle<v8::Value> Version(const v8::Arguments& args) {
return v8::String::New(v8::V8::GetVersion());
}
// Reads a file into a v8 string.
v8::Handle<v8::String> ReadFile(const char* name) {
FILE* file = fopen(name, "rb");
if (file == NULL) return v8::Handle<v8::String>();
fseek(file, 0, SEEK_END);
int size = ftell(file);
rewind(file);
char* chars = new char[size + 1];
chars[size] = '\0';
for (int i = 0; i < size;) {
int read = fread(&chars[i], 1, size - i, file);
i += read;
}
fclose(file);
v8::Handle<v8::String> result = v8::String::New(chars, size);
delete[] chars;
return result;
}
// The read-eval-execute loop of the shell.
void RunShell(v8::Handle<v8::Context> context) {
printf("V8 version %s\n", v8::V8::GetVersion());
static const int kBufferSize = 256;
while (true) {
char buffer[kBufferSize];
printf("> ");
char* str = fgets(buffer, kBufferSize, stdin);
if (str == NULL) break;
v8::HandleScope handle_scope;
ExecuteString(v8::String::New(str),
v8::String::New("(shell)"),
true,
true);
}
printf("\n");
}
// Executes a string within the current v8 context.
bool ExecuteString(v8::Handle<v8::String> source,
v8::Handle<v8::Value> name,
bool print_result,
bool report_exceptions) {
// v8::HandleScope handle_scope;
/*
v8::String::Utf8Value str(source);
char *s1, *s2;
// char *s1 = *str;
// for(int i=0;s1[i]!='\n';++i);
std::string s = (*str);
std::string::size_type p = s.find('\n');
if (!strncmp((*s.c_str()),"import(\"",p)) {
s1 = new char[s.size() - p + 1];
strcpy(s1,s.c_str() + p);
s1[s.size() - p] = 0;
v8::Handle<v8::String> src = v8::String::New(s1,s.size()-p);
s = s.substr(s.find('\"')+1,p);
s = s.substr(0,s.rfind('\"'));
// std::cout << s << std::endl;
// s1 = &s[0];
printf("%s\n",s1);
*/
/*
std::cmatch res;
printf("A\n");
fflush(stdout);
// std::regex rx("[ ]*import[ ]*\\([ ]*([.]+)[ ]*\\)[ ]*;[ ]*\\n");
std::regex rx("import(1)");
printf("B\n");
fflush(stdout);
std::regex_search(*str, res, rx);
printf("C:%s\n",*str);
fflush(stdout);
std::string r1(res[0]);
// const char *s = r1.c_str();
if (s==NULL) {
printf("null\n");
} else {
printf("%s\n",s);
}
fflush(stdout);
*/
// std::cout << std::string(res[0]) << "\n";
/*
std::string r1(res[1]);
std::string r2(res[2]);
printf("D\n");
fflush(stdout);
printf("\n%s. %s\n",r1.c_str(),r2.c_str());
printf("F\n");
fflush(stdout);
exit;
*/
v8::TryCatch try_catch;
v8::Handle<v8::Script> script = v8::Script::Compile(source, name);
if (script.IsEmpty()) {
// Print errors that happened during compilation.
if (report_exceptions)
ReportException(&try_catch);
return false;
} else {
v8::Handle<v8::Value> result = script->Run();
if (result.IsEmpty()) {
// Print errors that happened during execution.
if (report_exceptions)
ReportException(&try_catch);
return false;
} else {
if (print_result && !result->IsUndefined()) {
// If all went well and the result wasn't undefined then print
// the returned value.
v8::String::Utf8Value str(result);
printf("%s\n", *str);
}
return true;
}
}
}
void ReportException(v8::TryCatch* try_catch) {
v8::HandleScope handle_scope;
v8::String::Utf8Value exception(try_catch->Exception());
v8::Handle<v8::Message> message = try_catch->Message();
if (message.IsEmpty()) {
// V8 didn't provide any extra information about this error; just
// print the exception.
printf("%s\n", *exception);
} else {
// Print (filename):(line number): (message).
v8::String::Utf8Value filename(message->GetScriptResourceName());
int linenum = message->GetLineNumber();
printf("%s:%i: %s\n", *filename, linenum, *exception);
// Print line of source code.
v8::String::Utf8Value sourceline(message->GetSourceLine());
printf("%s\n", *sourceline);
// Print wavy underline (GetUnderline is deprecated).
int start = message->GetStartColumn();
for (int i = 0; i < start; i++) {
printf(" ");
}
int end = message->GetEndColumn();
for (int i = start; i < end; i++) {
printf("^");
}
printf("\n");
}
}
#include <v8.h>
//#include <fcntl.h>
#include <string.h>
#include <stdio.h>
//#include <stdlib.h>
#include <iostream>
//#include <string>
#include "toc.h"
// The callback that is invoked by v8 whenever the JavaScript 'printf'
// function is called. Prints its arguments on stdout separated by
// spaces and ending with a newline.
v8::Handle<v8::Value> Rename(const v8::Arguments& args) {
int rv;
v8::Handle<v8::Value> v8rv;
rv = rename(
(* v8::String::Utf8Value(args[0])),
(* v8::String::Utf8Value(args[1]))
);
v8rv = v8::Handle<v8::Value>((v8::Value*)(&rv));
return(v8rv);
// return v8::Number(&rv);
// return (v8::Number::ToNumber()) rv;
}
char *symtab[] = {
"rename",
NULL
};
extern "C" char **startup()
{
printf("1\n");
fflush(stdout);
return(symtab);
// printf("2\n");
// fflush(stdout);
}
teste3.js
Description: JavaScript source
