/***************************************************************************
* Copyright (C) 2006 by TAM(Teppei Tamra) *
* tam-t@par.odn.ne.jp *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "jsproc.h"
#define XP_UNIX 1
#define SVR4 1
#define SYSV 1
#define _BSD_SOURCE 1
#define POSIX_SOURCE 1
#define DARWIN 1
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <jsapi.h>
#include <string.h>
namespace Honoka {
class JSProcPriv {
public:
JSRuntime *jsrt;
JSContext *jsct;
JSObject *jsobj;
JSClass jscs;
JSProcPriv() {
jscs.name = "global";
jscs.flags = JSCLASS_NEW_RESOLVE;
jscs.addProperty = JS_PropertyStub;
jscs.delProperty = JS_PropertyStub;
jscs.getProperty = JS_PropertyStub;
jscs.setProperty = JS_PropertyStub;
jscs.enumerate = enumerate;
jscs.resolve = (JSResolveOp)resolve;
jscs.convert = JS_ConvertStub;
jscs.finalize = JS_FinalizeStub;
jsrt = NULL;
jsct = NULL;
jsobj = NULL;
};
static JSBool resolve(JSContext *context,JSObject *obj,jsval id,uintN flags,JSObject **objp) {
return JS_TRUE;
};
static JSBool enumerate(JSContext *context,JSObject *obj)
{
return JS_EnumerateStandardClasses(context,obj);
};
};
}
JSProc::JSProc(const string &filename)
{
jspriv = new JSProcPriv();
init(filename);
}
void JSProc::init(const string &filename)
{
if (jspriv->jsct) JS_DestroyContext(jspriv->jsct);
if (jspriv->jsrt) JS_DestroyRuntime(jspriv->jsrt);
int fd = open(filename.c_str(),O_RDONLY);
if (fd == -1) return;
off_t mmapsize = lseek(fd,0,SEEK_END);
char * mmapptr = (char *)mmap(0,mmapsize,PROT_READ,MAP_PRIVATE,fd,0);
jspriv->jsrt = JS_NewRuntime(64L * 1024L * 1024L);
if (!jspriv->jsrt) return;
jspriv->jsct = JS_NewContext(jspriv->jsrt, 8192);
if (!jspriv->jsct) {
JS_DestroyRuntime(jspriv->jsrt);
jspriv->jsrt = NULL;
munmap(mmapptr,mmapsize);
close(fd);
return;
}
jspriv->jsobj = JS_NewObject(jspriv->jsct,&jspriv->jscs, NULL, NULL);
if (!jspriv->jsobj) {
JS_DestroyContext(jspriv->jsct);
jspriv->jsct = NULL;
JS_DestroyRuntime(jspriv->jsrt);
jspriv->jsrt = NULL;
munmap(mmapptr,mmapsize);
close(fd);
return;
}
if (!JS_InitStandardClasses(jspriv->jsct,jspriv->jsobj)) {
JS_DestroyContext(jspriv->jsct);
jspriv->jsct = NULL;
JS_DestroyRuntime(jspriv->jsrt);
jspriv->jsrt = NULL;
munmap(mmapptr,mmapsize);
close(fd);
return;
}
jsval rval;
JSString *str;
uintN lino;
if (!JS_EvaluateScript(jspriv->jsct,jspriv->jsobj,mmapptr,mmapsize,"script",lino, &rval)) {
JS_DestroyContext(jspriv->jsct);
jspriv->jsct = NULL;
JS_DestroyRuntime(jspriv->jsrt);
jspriv->jsrt = NULL;
munmap(mmapptr,mmapsize);
close(fd);
return;
}
munmap(mmapptr,mmapsize);
close(fd);
return;
}
JSProc::~JSProc()
{
if (jspriv->jsct) JS_DestroyContext(jspriv->jsct);
if (jspriv->jsrt) JS_DestroyRuntime(jspriv->jsrt);
delete jspriv;
}
/*!
\fn JSProc::eval(const string &script)
*/
string JSProc::eval(const string &script)
{
if (!jspriv->jsct) return string();
jsval rval;
JSString *str;
char fn[] = "(inline)";
uintN lino = 0;
if (!JS_EvaluateScript(jspriv->jsct,jspriv->jsobj,script.c_str(),strlen(script.c_str()),fn,lino, &rval)) {
return string();
}
str = JS_ValueToString(jspriv->jsct,rval);
return string(JS_GetStringBytes(str),strlen(JS_GetStringBytes(str)));
}