Additional xpcom support for JS. Currently not in use by anyone. See MyScriptable.{h,cpp}

for an example of how to use this interface.


git-svn-id: svn://10.0.0.236/trunk@7252 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
bjorn%netscape.com 1998-08-04 20:34:20 +00:00
parent 92be964d2d
commit 30ead9145f
12 changed files with 1035 additions and 84 deletions

View File

@ -0,0 +1,3 @@
#include "JSWrapper.h"
NS_IMPL_ISUPPORTS(Scriptable(JSWrapper), kIScriptableIID);

View File

@ -0,0 +1,51 @@
#ifndef _JSWrapper
#define _JSWrapper
#include "jsIScriptable.h"
extern const JS_PUBLIC_DATA(nsIID) kIScriptableIID;
// this class makes a JS object be scriptable
DefScriptableClass(JSWrapper);
class JSWrapper : public Scriptable(JSWrapper) {
JSContext* cx;
JSObject* obj;
public:
JSWrapper(JSContext* _cx, JSObject* _obj) : obj(_obj), Scriptable(JSWrapper)() {
jsval v = OBJECT_TO_JSVAL(obj);
JS_AddRoot(cx,&v);
}
~JSWrapper() {
jsval v = OBJECT_TO_JSVAL(obj);
JS_RemoveRoot(cx,&v);
}
JSObject* GetJS() {
return obj;
}
void SetJS(JSObject *o) {
obj = o;
}
nsresult get(JSContext* cx, char* p, jsval* vp) {
return (JS_GetProperty(cx,obj,p,vp) == JS_TRUE ? NS_OK : NS_ERROR_FAILURE);
}
nsresult put(JSContext* cx, char* p, jsval v) {
return (JS_SetProperty(cx,obj,p,&v) == JS_TRUE ? NS_OK : NS_ERROR_FAILURE);
}
char** GetIds() {
return NULL;
}
JSObject *getParent(JSContext* cx) {
return JS_GetParent(cx,obj);
}
void setParent(JSContext* cx, JSObject *o) {
JS_SetParent(cx,obj,o);
}
JSObject* getProto(JSContext* cx) {
return JS_GetPrototype(cx, obj);
}
void setProto(JSContext* cx, JSObject *o) {
JS_SetPrototype(cx,obj,o);
}
};
#endif

View File

@ -0,0 +1,55 @@
#include "MyScriptable.h"
NS_IMPL_ISUPPORTS(Scriptable(MyScriptable), kIScriptableIID);
nsresult
MyScriptable::m(JSContext* cx, int argc, jsval* args, jsval* rval)
{
if (argc<1)
return NS_ERROR_FAILURE;
double d;
if (FromJS(cx,args[0],&d) != NS_OK)
return NS_ERROR_FAILURE;
return ToJS(cx,m(d),rval);
}
nsresult
MyScriptable::get(JSContext* cx, char* p, jsval* vp)
{
Meth* meth;
if (strcmp(p,"x") == 0)
return ToJS(cx,x,vp);
else if (strcmp(p,"y") == 0)
return ToJS(cx,y,vp);
else if (GetMethod("m",&meth) == NS_OK)
return ToJS(cx,meth,vp);
else
return NS_ERROR_FAILURE;
}
nsresult
MyScriptable::put(JSContext* cx, char* p, jsval v)
{
double d;
if (FromJS(cx,v,&d) != NS_OK)
return NS_ERROR_FAILURE;
if (strcmp(p,"x") == 0) {
x = d;
return NS_OK;
}
else if (strcmp(p,"y") == 0) {
y = d;
return NS_OK;
}
else
return NS_ERROR_FAILURE;
}
extern "C" {
JS_PUBLIC_API(jsIScriptable*)
CreateInstance(JSContext* cx)
{
jsIScriptable* jsi = new MyScriptable();
return jsi;
}
}

View File

@ -0,0 +1,23 @@
#include "jsIScriptable.h"
extern const PR_IMPORT_DATA(nsIID) kIScriptableIID;
// this implements an instance of jsIScriptable to
// be loaded into JS.
DefScriptableClass(MyScriptable);
class MyScriptable : public Scriptable(MyScriptable) {
public:
int x,y;
int m(int a) {
return a*a;
}
nsresult m(JSContext* cx, int argc, jsval* args, jsval* rval);
MyScriptable(int _x=42,int _y=99) :
x(_x), y(_y), Scriptable(MyScriptable)(1) {
AddMethod("m",&MyScriptable::m);
}
nsresult get(JSContext* cx, char* p, jsval* vp);
nsresult put(JSContext* cx, char* p, jsval v);
};

View File

@ -20,13 +20,9 @@
* jsContext.cpp -- implementation of the jsIContext interface for the JSAPI.
*/
extern "C" {
#include <jsapi.h>
}
#include <nsISupports.h>
#include "jsIScriptable.h"
#include "jsContext.h"
#include "jsScriptable.h"
#include "JSWrapper.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIContextIID, JS_ICONTEXT_IID);
@ -68,7 +64,7 @@ jsContext::~jsContext()
}
JSContext *
jsContext::getJSContext()
jsContext::GetJS()
{
return cx;
}
@ -185,7 +181,7 @@ jsContext::toScriptable(jsval v, jsIScriptable *scope)
JSObject *jsScriptableCreateJSObjectProxy(jsIContext *cx, jsIScriptable *scope)
{
JSObject *obj = ((jsScriptable *)scope)->getJSObject(cx);
JSObject *obj = scope->GetJS();
if (!obj) {
/* XXX construct a proxy object */
return NULL;
@ -195,7 +191,7 @@ JSObject *jsScriptableCreateJSObjectProxy(jsIContext *cx, jsIScriptable *scope)
jsIScriptable *jsScriptableCreateFromJSObject(jsIContext *cx, JSObject *obj)
{
return new jsScriptable(cx, obj);
return new JSWrapper(cx->GetJS(), obj);
}
nsresult
@ -205,7 +201,7 @@ jsContext::evaluateString(jsIScriptable *scope,
uintN lineno,
jsval *rval)
{
JSObject *obj = scope->getJSObject(this);
JSObject *obj = scope->GetJS();
if (!obj)
return NS_ERROR_FAILURE;
if (!JS_EvaluateScript(cx, obj, JS_GetStringBytes(source),
@ -220,7 +216,7 @@ jsContext::evaluateString(jsIScriptable *scope,
nsresult
jsContext::initStandardObjects(jsIScriptable *scope)
{
JSObject *obj = scope->getJSObject(this);
JSObject *obj = scope->GetJS();
if (!obj)
return NS_ERROR_FAILURE;
if (!JS_InitStandardClasses(cx, obj))

View File

@ -3,7 +3,6 @@
#include "jsIContext.h"
#include "jsRuntime.h"
#include "jsScriptable.h"
static void ErrorReporterHandler(JSContext *cx, const char *message,
JSErrorReport *report);
@ -19,7 +18,7 @@ public:
/**
* We shouldn't need this, but for now...
*/
JSContext *getJSContext(void);
JSContext *GetJS(void);
jsIFunction *compileFunction(jsIScriptable *scope,
JSString *source,
JSString *sourceName,
@ -74,7 +73,6 @@ public:
JSBool removeRoot(void *root);
friend class jsRuntime;
friend class jsScriptable;
friend void ErrorReporterHandler(JSContext *cx, const char *message,
JSErrorReport *report);
NS_DECL_ISUPPORTS

View File

@ -25,10 +25,8 @@ class jsIContext;
#ifndef JS_ICONTEXT_H
#define JS_ICONTEXT_H
#include <nsISupports.h>
#include <jsapi.h>
#include "jsIScript.h"
#include "jsIScriptable.h"
#include "jsIScript.h"
#include "jsIFunction.h"
#include "jsIErrorReporter.h"
@ -42,6 +40,7 @@ class jsIContext;
class jsIContext: public nsISupports {
public:
virtual JSContext* GetJS() =0;
/**
* Compile a JavaScript function.
* @return NULL on error, compiled jsIFunction *otherwise.
@ -116,7 +115,7 @@ class jsIContext: public nsISupports {
* Note: the return value indicates the success of the operation,
* not the resulting boolean value. *bp stores the new boolean value.
*/
NS_IMETHOD toBoolean(jsval v, JSBool *bp) = 0;
virtual nsresult toBoolean(jsval v, JSBool *bp) = 0;
/**
* Convert a jsval to a (newly-allocated) JavaScript number value.
@ -137,7 +136,7 @@ class jsIContext: public nsISupports {
/**
* Evaluate a JavaScript source string.
*/
NS_IMETHOD evaluateString(jsIScriptable *scope,
virtual nsresult evaluateString(jsIScriptable *scope,
JSString *source,
JSString *sourceName,
uintN lineno,
@ -147,7 +146,7 @@ class jsIContext: public nsISupports {
* Initialize the standard (ECMA-plus) objects in the given scope.
* Makes scope an ECMA `global object'.
*/
NS_IMETHOD initStandardObjects(jsIScriptable *scope) = 0;
virtual nsresult initStandardObjects(jsIScriptable *scope) = 0;
/**
* Report a (usually fatal) runtime error.

View File

@ -0,0 +1,296 @@
#include "JSWrapper.h"
#include "../prassert.h"
extern const JS_PUBLIC_DATA(nsIID) kIScriptableIID = JS_ISCRIPTABLE_IID;
static JSBool
JS_IScriptableGetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
if (!JSVAL_IS_STRING(id))
return JS_FALSE;
// do ints later
jsIScriptable* jsi = (jsIScriptable*)JS_GetPrivate(cx,obj);
PR_ASSERT(jsi);
JSString *jstr = JSVAL_TO_STRING(id);
char* prop = JS_GetStringBytes(jstr);
return (jsi->get(cx,prop,vp) == NS_OK ? JS_TRUE : JS_FALSE);
}
JSBool
JS_IScriptableSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
if (!JSVAL_IS_STRING(id))
return JS_FALSE;
// do ints later
jsIScriptable* jsi = (jsIScriptable*)JS_GetPrivate(cx,obj);
PR_ASSERT(jsi);
JSString *jstr = JSVAL_TO_STRING(id);
char* prop = JS_GetStringBytes(jstr);
return (jsi->put(cx,prop,*vp) == NS_OK ? JS_TRUE : JS_FALSE);
}
static void
Scriptable_Finalize(JSContext *cx, JSObject *obj)
{
jsIScriptable* jsi;
jsi = (jsIScriptable*)JS_GetPrivate(cx,obj);
if (jsi)
jsi->Release();
}
static JSClass IScriptableWrapper_class = {
"IScriptableWrapper",
JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE,
JS_PropertyStub,JS_PropertyStub,
JS_IScriptableGetProperty,JS_IScriptableSetProperty,
JS_EnumerateStub,JS_ResolveStub,
JS_ConvertStub,Scriptable_Finalize
};
JS_PUBLIC_API(nsresult)
jsIScriptable::FromJS(JSContext* cx, jsval v, double* d)
{
if (JSVAL_IS_DOUBLE(v)) {
*d = *JSVAL_TO_DOUBLE(v);
return NS_OK;
}
else if (JSVAL_IS_INT(v)) {
int i = JSVAL_TO_INT(v);
*d = (double)i;
return NS_OK;
}
else
return NS_ERROR_FAILURE;
}
JS_PUBLIC_API(nsresult)
jsIScriptable::FromJS(JSContext* cx, jsval v, char** s, size_t n)
{
if (JSVAL_IS_STRING(v)) {
JSString *jstr = JSVAL_TO_STRING(v);
char* str = JS_GetStringBytes(jstr);
strncpy(*s, str, n);
return NS_OK;
}
else
return NS_ERROR_FAILURE;
}
JS_PUBLIC_API(nsresult)
jsIScriptable::FromJS(JSContext* cx, jsval v, jsIScriptable** o)
{
if (JSVAL_IS_OBJECT(v)) {
JSObject* jobj = JSVAL_TO_OBJECT(v);
JSClass* jclass = JS_GetClass(cx,jobj);
if (strcmp(jclass->name,"IScriptableWrapper") == 0) {
*o = (jsIScriptable*)JS_GetPrivate(cx,jobj);
return NS_OK;
}
else {
*o = (jsIScriptable*)new JSWrapper(cx,jobj);
if (*o == NULL)
return NS_ERROR_FAILURE;
else
return NS_OK;
}
}
else
return NS_ERROR_FAILURE;
}
static JSBool
MethodCall(JSContext *cx,JSObject *obj,uintN argc,jsval *argv,jsval *vp)
{
JSObject* meth_obj;
void* p;
meth_obj = JSVAL_TO_OBJECT(argv[-2]);
p = JS_GetPrivate(cx,meth_obj);
PR_ASSERT(p);
Meth* meth = (Meth*)p;
return (meth->invoke(argc,argv,vp) == NS_OK ? JS_TRUE : JS_FALSE);
}
static JSBool
Method_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
{
*vp = OBJECT_TO_JSVAL(obj);
return JS_TRUE;
}
static void
Method_Finalize(JSContext *cx, JSObject *obj)
{
Meth* meth;
meth = (Meth*)JS_GetPrivate(cx,obj);
if (meth)
meth->SubRef();
}
static JSBool
Method_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
JSObject **objp, JSProperty **propp
#if defined JS_THREADSAFE && defined DEBUG
, const char *file, uintN line
#endif
)
{
return JS_TRUE;
}
static JSBool
Method_defineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
JSPropertyOp getter, JSPropertyOp setter,
uintN attrs, JSProperty **propp)
{
return JS_FALSE;
}
static JSBool
Method_getAttributes(JSContext *cx, JSObject *obj, jsid id,
JSProperty *prop, uintN *attrsp)
{
return JS_FALSE;
}
static JSBool
Method_setAttributes(JSContext *cx, JSObject *obj, jsid id,
JSProperty *prop, uintN *attrsp)
{
return JS_TRUE;
}
static JSBool
Method_deleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
return JS_FALSE;
}
static JSBool
Method_defaultValue(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
{
return JS_TRUE;
}
PR_STATIC_CALLBACK(JSBool)
Method_getProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
return JS_TRUE;
}
PR_STATIC_CALLBACK(JSBool)
Method_setProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
return JS_TRUE;
}
static JSBool
Method_newEnumerate(JSContext *cx,JSObject *obj,JSIterateOp enum_op,jsval *statep,jsid *idp)
{
return JS_TRUE;
}
static JSBool
Method_checkAccess(JSContext *cx, JSObject *obj, jsid id,
JSAccessMode mode, jsval *vp, uintN *attrsp)
{
return JS_TRUE;
}
JSBool MethodCall(JSContext*,JSObject*,uintN,jsval*,jsval*);
JSObjectOps Method_ops = {
/* Mandatory non-null function pointer members. */
NULL, /* newObjectMap */
NULL, /* destroyObjectMap */
Method_lookupProperty,
Method_defineProperty,
Method_getProperty,
Method_setProperty,
Method_getAttributes,
Method_setAttributes,
Method_deleteProperty,
Method_defaultValue,
Method_newEnumerate,
Method_checkAccess,
/* Optionally non-null members start here. */
NULL, /* thisObject */
NULL, /* dropProperty */
MethodCall, /* call */
NULL, /* construct */
NULL, /* xdrObject */
NULL, /* hasInstance */
};
extern "C" PR_IMPORT_DATA(JSObjectOps) js_ObjectOps;
JSObjectOps *
Method_getObjectOps(JSContext *cx, JSClass *clazz)
{
if (Method_ops.newObjectMap == NULL) {
Method_ops.newObjectMap = js_ObjectOps.newObjectMap;
Method_ops.destroyObjectMap = js_ObjectOps.destroyObjectMap;
}
return &Method_ops;
}
static JSClass MethodWrapper_class = {
"MethodWrapper", JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, Method_Convert, Method_Finalize,
Method_getObjectOps,
};
JS_PUBLIC_API(nsresult)
jsIScriptable::ToJS(JSContext* cx, double d, jsval* v)
{
return (JS_NewDoubleValue(cx,d,v) == JS_TRUE ? NS_OK : NS_ERROR_FAILURE);
}
JS_PUBLIC_API(nsresult)
jsIScriptable::ToJS(JSContext* cx, char* s, jsval* v)
{
JSString* jstr = JS_NewStringCopyZ(cx, s);
if (jstr == NULL)
return NS_ERROR_FAILURE;
*v = STRING_TO_JSVAL(jstr);
return NS_OK;
}
JS_PUBLIC_API(nsresult)
jsIScriptable::ToJS(JSContext* cx, jsIScriptable* jsi, jsval* v)
{
JSObject* jobj = jsi->GetJS();
if (jobj == NULL) {
jobj = JS_NewObject(cx,&IScriptableWrapper_class,NULL,NULL);
if (jobj == NULL)
return NS_ERROR_FAILURE;
jsi->SetJS(jobj);
jsi->AddRef();
JS_SetPrivate(cx,jobj,(void*)jsi);
}
*v = OBJECT_TO_JSVAL(jobj);
return NS_OK;
}
JS_PUBLIC_API(nsresult)
jsIScriptable::ToJS(JSContext* cx, Meth* meth, jsval* vp)
{
jsval v = meth->GetJSVal(cx);
if (v) {
*vp = v;
return NS_OK;
}
JSObject* meth_obj = JS_NewObject(cx,&MethodWrapper_class,NULL,NULL);
if (meth_obj == NULL)
return NS_ERROR_FAILURE;
*vp = OBJECT_TO_JSVAL(meth_obj);
JS_SetPrivate(cx,meth_obj,(void*)meth);
meth->SetJSVal(cx,*vp);
meth->SetJSContext(cx);
meth->AddRef();
return NS_OK;
}

View File

@ -1,71 +1,153 @@
/* -*- Mode: cc; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
* jsIScriptable.h -- the XPCOM interface to native JavaScript objects.
*/
class jsIScriptable; /* for mutually-dependent includes */
#ifndef JS_ISCRIPTABLE_H
#define JS_ISCRIPTABLE_H
#ifndef _jsIScriptable
#define _jsIScriptable
#include "jsapi.h"
#include "nsISupports.h"
#include "jsIContext.h"
#include <jsapi.h>
#define JS_ISCRIPTABLE_IID \
{ 0, 0, 0, \
{0, 0, 0, 0, 0, 0, 0, 0}}
#define JSSCRIPTABLE_NOT_FOUND -1
class jsIScriptable: public nsISupports {
public:
virtual JSString *getClassName(jsIContext *) = 0;
/* XXX use jsid for name/index? */
NS_IMETHOD get(jsIContext *cx, const char *name, jsval *vp) = 0;
NS_IMETHOD has(jsIContext *cx, jsval id, JSBool *bp) = 0;
NS_IMETHOD put(jsIContext *cx, const char *name, jsval v) = 0;
NS_IMETHOD del(jsIContext *cx, jsval id) = 0;
virtual jsIScriptable *getPrototype(jsIContext *cx) = 0;
NS_IMETHOD setPrototype(jsIContext *cx, jsIScriptable *prototype) = 0;
virtual jsIScriptable *getParentScope(jsIContext *cx) = 0;
NS_IMETHOD setParentScope(jsIContext *cx, jsIScriptable *parent) = 0;
/* virtual JSIdArray *getIds(); */
NS_IMETHOD getDefaultValue(jsIContext *cx, JSType hint, jsval *vp) = 0;
/**
* Return a classic JSAPI JSObject * for this object.
* Return NULL if you don't know how to, and the engine will
* construct a proxy for you.
*/
virtual JSObject *getJSObject(jsIContext *) = 0;
/**
* Set the JSObject proxy for this object (typically one created
* by the engine in response to a NULL return fron getJSObject).
* Context is provided for GC rooting and other tasks. Be sure
* to unroot the proxy in your destructor, etc.
*/
NS_IMETHOD setJSObject(jsIContext *, JSObject *)= 0;
class Meth {
public:
virtual nsresult invoke(int argc, jsval* args, jsval* rval) =0;
virtual void SetJSContext(JSContext* cx) =0;
virtual JSContext* GetJSContext() =0;
virtual void SetJSVal(JSContext* cx, jsval v) =0;
virtual jsval GetJSVal(JSContext* cx) =0;
virtual int AddRef() =0;
virtual int SubRef() =0;
};
#endif /* JS_ISCRIPTABLE_H */
#define Method(C) Method_##C
#define DefMethodClass(C)\
class C;\
class Method_##C : public Meth {\
JSContext* cx; \
jsval mval;\
int _ref;\
public:\
C* thisptr; \
nsresult (C::*method)(JSContext* cx, int argc, jsval* args, jsval* rval);\
virtual nsresult invoke(int argc, jsval* args, jsval* rval) {\
return (thisptr->*method)(cx,argc,args,rval);\
}\
virtual void SetJSContext(JSContext* _cx) {\
cx = _cx;\
}\
virtual JSContext* GetJSContext() {\
return cx;\
}\
virtual void SetJSVal(JSContext* cx, jsval v) {\
if (mval)\
JS_RemoveRoot(cx,&mval);\
mval = v;\
JS_AddRoot(cx,&mval);\
}\
virtual jsval GetJSVal(JSContext* cx) {\
return mval;\
}\
virtual int AddRef() {\
return _ref++;\
}\
virtual int SubRef() {\
return --_ref;\
}\
Method_##C() : cx(NULL), mval(0), _ref(0) {}\
~Method_##C() {\
if (mval)\
JS_RemoveRoot(cx,&mval);\
}\
}
class jsIScriptable : public nsISupports {
public:
// static conversion between JS and C++
static JS_PUBLIC_API(nsresult) FromJS(JSContext* cx, jsval v, double* d);
static JS_PUBLIC_API(nsresult) FromJS(JSContext* cx, jsval v, char** s, size_t n);
static JS_PUBLIC_API(nsresult) FromJS(JSContext* cx, jsval v, jsIScriptable** o);
static JS_PUBLIC_API(nsresult) ToJS(JSContext* cx, double d, jsval* v);
static JS_PUBLIC_API(nsresult) ToJS(JSContext* cx, char* s, jsval* v);
static JS_PUBLIC_API(nsresult) ToJS(JSContext* cx, jsIScriptable* o, jsval* v);
static JS_PUBLIC_API(nsresult) ToJS(JSContext* cx, Meth* m, jsval* v);
virtual JSObject* GetJS() =0; // returns the peer JS object
virtual void SetJS(JSObject *o) =0; // sets the peer
virtual nsresult get(JSContext* cx, char* p, jsval* v) =0; // gets the property
virtual nsresult put(JSContext* cx, char* p, jsval v) =0; // sets ...
virtual char** GetIds() =0; // returns an array with the identifiers (ints or strings) that can be enumerated
virtual JSObject *getParent(JSContext* cx) =0;
virtual void setParent(JSContext* cx, JSObject *o) =0;
virtual JSObject* getProto(JSContext* cx) =0;
virtual void setProto(JSContext* cx, JSObject *o) =0;
};
#define Scriptable(C) jsScriptable_##C
#define DefScriptableClass(C)\
DefMethodClass(C);\
class jsScriptable_##C : public jsIScriptable {\
JSObject* obj;\
int _ref;\
int sz;\
char** names;\
Method(C)* meths;\
public:\
NS_DECL_ISUPPORTS;\
jsScriptable_##C(int _sz=0) : _ref(0), sz(_sz), obj(NULL) {\
names = new char*[sz];\
meths = new Method(C)[sz];\
for (int i=0; i<sz; i++)\
names[i] = NULL;\
}\
~jsScriptable_##C() {\
delete names;\
delete meths;\
}\
nsresult AddMethod(char* nm, nsresult (C::*method)(JSContext*, int, jsval*, jsval*)) {\
for (int i=0; i<sz; i++) \
if (names[i] == NULL) {\
names[i] = nm;\
meths[i].method = method;\
meths[i].thisptr = (C*)this;\
return NS_OK;\
}\
return NS_ERROR_FAILURE;\
}\
nsresult GetMethod(char* nm, Meth** meth) {\
for (int i=0; i<sz; i++) \
if (strcmp(names[i],nm) == 0) {\
*meth = &meths[i];\
return NS_OK;\
}\
return NS_ERROR_FAILURE;\
}\
nsresult RemoveMethod(char* nm) {\
for (int i=0; i<sz; i++) \
if (strcmp(names[i],nm) == 0) {\
names[i] = NULL;\
return NS_OK;\
}\
return NS_ERROR_FAILURE;\
}\
virtual JSObject* GetJS() { \
return obj;\
}\
virtual void SetJS(JSObject *o) { \
obj = o; \
}\
char** GetIds() {\
return NULL;\
}\
virtual JSObject *getParent(JSContext* cx) {\
return (obj ? JS_GetParent(cx,obj) : NULL);\
}\
virtual void setParent(JSContext* cx, JSObject *o) {\
if (obj) JS_SetParent(cx,obj,o);\
}\
virtual JSObject* getPrototype(JSContext* cx) {\
return (obj ? JS_GetPrototype(cx, obj) : NULL);\
}\
virtual void setPrototype(JSContext* cx, JSObject *o) {\
if (obj) JS_SetPrototype(cx,obj,o);\
}\
};\
#endif

View File

@ -24,7 +24,7 @@
static NS_DEFINE_IID(kIRuntime, JS_IRUNTIME_IID);
static int jsRuntime::runtimeCount = 0;
int jsRuntime::runtimeCount = 0;
jsRuntime::jsRuntime(uint32 maxbytes)
{

View File

@ -0,0 +1,307 @@
extern "C" {
#include <stdio.h>
#include "jsapi.h"
#include "../prtypes.h"
#include "../prassert.h"
#include "../prlink.h"
extern PR_IMPORT_DATA(JSObjectOps) js_ObjectOps;
}
#include "jsIScriptable.h"
typedef nsISupports* (*FactoryFun)(JSContext*);
static JSClass global_class = {
"global", JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
};
struct FactoryStruct {
PRLibrary* lib;
FactoryFun create;
FactoryStruct(PRLibrary* _lib, FactoryFun _f) : lib(_lib), create(_f) {}
};
// this is the constructor for jsIScriptable objects
static JSBool
ExtensionsConstructor(JSContext *cx,JSObject *obj,uintN argc,jsval *argv,jsval *vp)
{
obj = JSVAL_TO_OBJECT(argv[-2]); // obj is now the factory
FactoryStruct* factory = (FactoryStruct*)JS_GetPrivate(cx,obj);
jsIScriptable* jsi = (jsIScriptable*)factory->create(cx);
return (jsIScriptable::ToJS(cx,jsi,vp) == NS_OK ? JS_TRUE : JS_FALSE);
}
static JSBool
Extensions_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
{
*vp = OBJECT_TO_JSVAL(obj);
return JS_TRUE;
}
static void
Extensions_Finalize(JSContext *cx, JSObject *obj)
{
FactoryStruct* factory;
factory = (FactoryStruct*)JS_GetPrivate(cx,obj);
if (factory) {
PR_UnloadLibrary(factory->lib);
delete factory;
}
}
static JSBool
Extensions_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
JSObject **objp, JSProperty **propp
#if defined JS_THREADSAFE && defined DEBUG
, const char *file, uintN line
#endif
)
{
return JS_TRUE;
}
static JSBool
Extensions_defineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
JSPropertyOp getter, JSPropertyOp setter,
uintN attrs, JSProperty **propp)
{
return JS_FALSE;
}
static JSBool
Extensions_getAttributes(JSContext *cx, JSObject *obj, jsid id,
JSProperty *prop, uintN *attrsp)
{
return JS_FALSE;
}
static JSBool
Extensions_setAttributes(JSContext *cx, JSObject *obj, jsid id,
JSProperty *prop, uintN *attrsp)
{
return JS_TRUE;
}
static JSBool
Extensions_deleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
return JS_FALSE;
}
static JSBool
Extensions_defaultValue(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
{
return JS_TRUE;
}
PR_STATIC_CALLBACK(JSBool)
Extensions_getProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
return JS_TRUE;
}
PR_STATIC_CALLBACK(JSBool)
Extensions_setProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
return JS_TRUE;
}
static JSBool
Extensions_newEnumerate(JSContext *cx,JSObject *obj,JSIterateOp enum_op,jsval *statep,jsid *idp)
{
return JS_TRUE;
}
static JSBool
Extensions_checkAccess(JSContext *cx, JSObject *obj, jsid id,
JSAccessMode mode, jsval *vp, uintN *attrsp)
{
return JS_TRUE;
}
JSBool ExtensionsConstructor(JSContext*,JSObject*,uintN,jsval*,jsval*);
JSObjectOps Extensions_ops = {
/* Mandatory non-null function pointer members. */
NULL, /* newObjectMap */
NULL, /* destroyObjectMap */
Extensions_lookupProperty,
Extensions_defineProperty,
Extensions_getProperty,
Extensions_setProperty,
Extensions_getAttributes,
Extensions_setAttributes,
Extensions_deleteProperty,
Extensions_defaultValue,
Extensions_newEnumerate,
Extensions_checkAccess,
/* Optionally non-null members start here. */
NULL, /* thisObject */
NULL, /* dropProperty */
ExtensionsConstructor, /* call */
ExtensionsConstructor, /* construct */
NULL, /* xdrObject */
NULL, /* hasInstance */
};
JSObjectOps *
Extensions_getObjectOps(JSContext *cx, JSClass *clazz)
{
return &Extensions_ops;
}
static JSClass Extensions_class = {
"Extensions", JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, Extensions_Convert, Extensions_Finalize,
Extensions_getObjectOps,
};
// resolving Extensions.M by assigning it to an object which each time it
// is called, constructs a new instance from M's factory.
static JSBool
Factory_Resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
JSObject **objp)
{
char *str;
JSObject *fact_obj;
if (!JSVAL_IS_STRING(id))
return JS_TRUE;
str = JS_GetStringBytes(JSVAL_TO_STRING(id));
// load factory.
PRLibrary* factory = PR_LoadLibrary(str);
if (factory == NULL)
return JS_FALSE;
FactoryFun fun = (FactoryFun)PR_FindSymbol(factory, "CreateInstance");
if (fun == NULL)
return JS_FALSE;
fact_obj = JS_DefineObject(cx, obj, str, &Extensions_class, NULL, 0);
JS_SetPrivate(cx,fact_obj,new FactoryStruct(factory,fun));
*objp = obj;
return JS_TRUE;
}
static JSClass Factory_class = {
"ExtensionsFactory",
JSCLASS_NEW_RESOLVE,
JS_PropertyStub,JS_PropertyStub,JS_PropertyStub,JS_PropertyStub,
JS_EnumerateStub,(JSResolveOp)Factory_Resolve,JS_ConvertStub,JS_FinalizeStub
};
static JSBool
Print(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
uintN i, n;
JSString *str;
for (i = n = 0; i < argc; i++) {
str = JS_ValueToString(cx, argv[i]);
if (!str)
return JS_FALSE;
printf("%s%s", i ? " " : "", JS_GetStringBytes(str));
n++;
}
if (n)
putchar('\n');
return JS_TRUE;
}
static void
Process(JSContext *cx, JSObject *obj, const char *filename)
{
JSScript *jsrc = JS_CompileFile(cx,obj,filename);
jsval rval;
if (jsrc == NULL) {
#ifdef DEBUG
printf("Failed compilation of %s\n",filename);
#endif
return;
}
if (!JS_ExecuteScript(cx,obj,jsrc,&rval)) {
#ifdef DEBUG
printf("Failed execution of %s\n",filename);
#endif
return;
}
}
static JSFunctionSpec helper_functions[] = {
/* name native nargs */
{"print", Print, 0},
{0}
};
static void
my_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
{
int i, j, k, n;
fputs("js: ", stderr);
if (!report) {
fprintf(stderr, "%s\n", message);
return;
}
if (report->filename)
fprintf(stderr, "%s, ", report->filename);
if (report->lineno)
fprintf(stderr, "line %u: ", report->lineno);
fputs(message, stderr);
if (!report->linebuf) {
putc('\n', stderr);
return;
}
fprintf(stderr, ":\n%s\n", report->linebuf);
n = report->tokenptr - report->linebuf;
for (i = j = 0; i < n; i++) {
if (report->linebuf[i] == '\t') {
for (k = (j + 8) & ~7; j < k; j++)
putc('.', stderr);
continue;
}
putc('.', stderr);
j++;
}
fputs("^\n", stderr);
}
int main(int argc, char* const* argv)
{
JSRuntime *rt;
JSContext *cx;
JSObject *glob, *ext;
const char *filename;
if (argc >= 2)
filename = (const char *) argv[1];
else
filename = (const char *) "test.js";
// JS init
rt = JS_Init(8L * 1024L * 1024L);
if (!rt)
return 0;
cx = JS_NewContext(rt, 8192);
PR_ASSERT(cx);
JS_SetErrorReporter(cx, my_ErrorReporter);
glob = JS_NewObject(cx, &global_class, NULL, NULL);
PR_ASSERT(glob);
if (!JS_InitStandardClasses(cx, glob))
return -1;
if (!JS_DefineFunctions(cx, glob, helper_functions))
return -1;
ext = JS_DefineObject(cx, glob, "Extensions", &Factory_class, NULL, 0);
if (!ext)
return -1;
Extensions_ops.newObjectMap = js_ObjectOps.newObjectMap;
Extensions_ops.destroyObjectMap = js_ObjectOps.destroyObjectMap;
Process(cx, glob, filename);
JS_DestroyContext(cx);
JS_DestroyRuntime(rt);
JS_ShutDown();
return 1;
}

View File

@ -0,0 +1,141 @@
# Microsoft Developer Studio Project File - Name="xpcom" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 5.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=xpcom - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "xpcom.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "xpcom.mak" CFG="xpcom - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "xpcom - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "xpcom - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "xpcom - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
!ELSEIF "$(CFG)" == "xpcom - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "EXPORT_JS_API" /D "_WIN32" /D "WIN32" /D "_DEBUG" /D "DEBUG" /D "XP_PC" /D "_WINDOWS" /D "JSFILE" /D "JS_THREADSAFE" /D "NSPR20" /FR /YX /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib H:\trees\ns\dist\WINNT4.0_DBG.OBJ\lib\libnspr21.lib h:\trees\mozilla.org\mozilla\dist\WIN32_D.OBJ\lib\xpcom32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "xpcom - Win32 Release"
# Name "xpcom - Win32 Debug"
# Begin Source File
SOURCE=.\jsContext.cpp
# End Source File
# Begin Source File
SOURCE=.\jsContext.h
# End Source File
# Begin Source File
SOURCE=.\jsIContext.h
# End Source File
# Begin Source File
SOURCE=.\jsIErrorReporter.h
# End Source File
# Begin Source File
SOURCE=.\jsIFunction.h
# End Source File
# Begin Source File
SOURCE=.\jsIRuntime.h
# End Source File
# Begin Source File
SOURCE=.\jsIScript.h
# End Source File
# Begin Source File
SOURCE=.\jsIScriptable.cpp
# End Source File
# Begin Source File
SOURCE=.\jsIScriptable.h
# End Source File
# Begin Source File
SOURCE=.\jsRuntime.cpp
# End Source File
# Begin Source File
SOURCE=.\jsRuntime.h
# End Source File
# Begin Source File
SOURCE=.\JSWrapper.cpp
# End Source File
# Begin Source File
SOURCE=.\JSWrapper.h
# End Source File
# End Target
# End Project