diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2010-12-08 03:52:21 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2010-12-08 03:52:21 +0000 |
commit | 2a70a69d92d1bd6071ff6ea76d724b458b4c2287 (patch) | |
tree | ddf28d01fbc256d858a4b1e323e5be6f082cbb81 /sca-cpp/trunk/modules/json | |
parent | 47017915e45f786265f5763ebf711abfe308738c (diff) |
Move JavaScript eval functions to the js module.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1043295 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sca-cpp/trunk/modules/json')
-rw-r--r-- | sca-cpp/trunk/modules/json/json-test.cpp | 15 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/json/json.hpp | 275 |
2 files changed, 14 insertions, 276 deletions
diff --git a/sca-cpp/trunk/modules/json/json-test.cpp b/sca-cpp/trunk/modules/json/json-test.cpp index abed71a9c3..6666b3f479 100644 --- a/sca-cpp/trunk/modules/json/json-test.cpp +++ b/sca-cpp/trunk/modules/json/json-test.cpp @@ -31,23 +31,13 @@ namespace tuscany { namespace json { -bool testJSEval() { - JSONContext cx; - const string script("(function testJSON(n){ return JSON.parse(JSON.stringify(n)) })(5)"); - jsval rval; - assert(JS_EvaluateScript(cx, cx.getGlobal(), c_str(script), (uintN)length(script), "testJSON.js", 1, &rval)); - const string r(JS_GetStringBytes(JS_ValueToString(cx, rval))); - assert(r == "5"); - return true; -} - ostream* jsonWriter(const string& s, ostream* os) { (*os) << s; return os; } bool testJSON() { - const JSONContext cx; + const js::JSContext cx; { const list<value> ad = mklist<value>(mklist<value>(attribute, "city", string("san francisco")), mklist<value>(attribute, "state", string("ca"))); @@ -91,7 +81,7 @@ bool testJSON() { } bool testJSONRPC() { - JSONContext cx; + js::JSContext cx; { const string lm("{\"id\": 1, \"method\": \"test\", \"params\": []}"); const list<value> e = content(readJSON(mklist(lm), cx)); @@ -166,7 +156,6 @@ bool testJSONRPC() { int main() { tuscany::cout << "Testing..." << tuscany::endl; - tuscany::json::testJSEval(); tuscany::json::testJSON(); tuscany::json::testJSONRPC(); diff --git a/sca-cpp/trunk/modules/json/json.hpp b/sca-cpp/trunk/modules/json/json.hpp index a0617b0e5e..a9dc57da15 100644 --- a/sca-cpp/trunk/modules/json/json.hpp +++ b/sca-cpp/trunk/modules/json/json.hpp @@ -26,194 +26,20 @@ * JSON data conversion functions. */ -#define XP_UNIX -#include <jsapi.h> #include "string.hpp" #include "list.hpp" #include "value.hpp" #include "element.hpp" #include "monad.hpp" +#include "../js/eval.hpp" namespace tuscany { namespace json { /** - * Report JSON errors. - */ -void reportError(unused JSContext *cx, const char *message, JSErrorReport *report) { -#ifdef WANT_MAINTAINER_MODE - cdebug << (const char*)(report->filename? report->filename : "<no filename>") << ":" - << (int)report->lineno << ":" << message << endl; -#endif -} - -/** - * Encapsulates a JavaScript runtime. Shared by multiple threads in - * a process. - */ -class JSONRuntime { -public: - JSONRuntime() { - // Create JS runtime - rt = JS_NewRuntime(8L * 1024L * 1024L); - if(rt == NULL) - cleanup(); - } - - operator JSRuntime*() const { - return rt; - } -private: - bool cleanup() { - if(rt != NULL) { - JS_DestroyRuntime(rt); - rt = NULL; - } - JS_ShutDown(); - return true; - } - - JSRuntime* rt; -} jsRuntime; - -JSClass jsGlobalClass = { "global", JSCLASS_GLOBAL_FLAGS, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, JSCLASS_NO_OPTIONAL_MEMBERS}; - -/** - * Represents a JavaScript context. Create one per thread. - */ -class JSONContext { -public: - JSONContext() { - // Create JS context - cx = JS_NewContext(jsRuntime, 8192); - if(cx == NULL) - return; - JS_SetOptions(cx, JSOPTION_VAROBJFIX); - JS_SetVersion(cx, JSVERSION_DEFAULT); - JS_SetErrorReporter(cx, reportError); - - // Create global JS object - global = JS_NewObject(cx, &jsGlobalClass, NULL, NULL); - if(global == NULL) { - cleanup(); - return; - } - - // Populate global object with the standard globals, like Object and Array - if(!JS_InitStandardClasses(cx, global)) { - cleanup(); - return; - } - } - - ~JSONContext() { - cleanup(); - } - - operator JSContext*() const { - return cx; - } - - JSObject* getGlobal() const { - return global; - } - -private: - bool cleanup() { - if(cx != NULL) { - JS_DestroyContext(cx); - cx = NULL; - } - return true; - } - - JSContext* cx; - JSObject* global; -}; - -/** - * Returns true if a list represents a JS array. - */ -const bool isJSArray(const list<value>& l) { - if(isNil(l)) - return true; - const value v = car(l); - if (isSymbol(v)) - return false; - if(isList(v)) { - if(!isNil((list<value>)v) && isSymbol(car<value>(v))) - return false; - } - return true; -} - -/** - * Converts JS properties to values. - */ -const list<value> jsPropertiesToValues(const list<value>& propertiesSoFar, JSObject* o, JSObject* i, const JSONContext& cx) { - - const value jsValToValue(const jsval& jsv, const JSONContext& cx); - - jsid id; - if(!JS_NextProperty(cx, i, &id) || id == JSVAL_VOID) - return propertiesSoFar; - jsval jsv; - if(!JS_GetPropertyById(cx, o, id, &jsv)) - return propertiesSoFar; - const value val = jsValToValue(jsv, cx); - - jsval idv; - JS_IdToValue(cx, id, &idv); - if(JSVAL_IS_STRING(idv)) { - if (isNil(val) && !isList(val)) - return jsPropertiesToValues(propertiesSoFar, o, i, cx); - const string name = JS_GetStringBytes(JSVAL_TO_STRING(idv)); - if (substr(name, 0, 1) == atsign) - return jsPropertiesToValues(cons<value>(mklist<value>(attribute, c_str(substr(name, 1)), val), propertiesSoFar), o, i, cx); - if (isList(val) && !isJSArray(val)) - return jsPropertiesToValues(cons<value>(cons<value>(element, cons<value>(c_str(name), list<value>(val))), propertiesSoFar), o, i, cx); - return jsPropertiesToValues(cons<value> (mklist<value> (element, c_str(name), val), propertiesSoFar), o, i, cx); - } - return jsPropertiesToValues(cons(val, propertiesSoFar), o, i, cx); -} - -/** - * Converts a JS val to a value. - */ -const value jsValToValue(const jsval& jsv, const JSONContext& cx) { - switch(JS_TypeOfValue(cx, jsv)) { - case JSTYPE_STRING: { - return value(string(JS_GetStringBytes(JSVAL_TO_STRING(jsv)))); - } - case JSTYPE_BOOLEAN: { - return value((bool)JSVAL_TO_BOOLEAN(jsv)); - } - case JSTYPE_NUMBER: { - jsdouble jsd; - JS_ValueToNumber(cx, jsv, &jsd); - return value((double)jsd); - } - case JSTYPE_OBJECT: { - JSObject* o = JSVAL_TO_OBJECT(jsv); - if (o == NULL) - return value(); - JSObject* i = JS_NewPropertyIterator(cx, o); - if(i == NULL) - return value(list<value> ()); - const value pv = jsPropertiesToValues(list<value> (), o, i, cx); - return pv; - } - default: { - return value(); - } - } -} - -/** * Consumes JSON strings and populates a JS object. */ -failable<bool> consume(JSONParser* parser, const list<string>& ilist, const JSONContext& cx) { +failable<bool> consume(JSONParser* parser, const list<string>& ilist, const js::JSContext& cx) { if (isNil(ilist)) return true; JSString* jstr = JS_NewStringCopyZ(cx, c_str(car(ilist))); @@ -225,7 +51,7 @@ failable<bool> consume(JSONParser* parser, const list<string>& ilist, const JSON /** * Convert a list of strings representing a JSON document to a list of values. */ -const failable<list<value> > readJSON(const list<string>& ilist, const JSONContext& cx) { +const failable<list<value> > readJSON(const list<string>& ilist, const js::JSContext& cx) { jsval val; JSONParser* parser = JS_BeginJSONParse(cx, &val); if(parser == NULL) @@ -238,84 +64,7 @@ const failable<list<value> > readJSON(const list<string>& ilist, const JSONConte if(!hasContent(consumed)) return mkfailure<list<value> >(reason(consumed)); - return list<value>(jsValToValue(val, cx)); -} - -/** - * Converts a list of values to JS array elements. - */ -JSObject* valuesToJSElements(JSObject* a, const list<value>& l, int i, const JSONContext& cx) { - const jsval valueToJSVal(const value& val, const JSONContext& cx); - if (isNil(l)) - return a; - jsval pv = valueToJSVal(car(l), cx); - JS_SetElement(cx, a, i, &pv); - return valuesToJSElements(a, cdr(l), ++i, cx); -} - -/** - * Converts a value to a JS val. - */ -const jsval valueToJSVal(const value& val, const JSONContext& cx) { - JSObject* valuesToJSProperties(JSObject* o, const list<value>& l, const JSONContext& cx); - - switch(type(val)) { - case value::String: - case value::Symbol: { - return STRING_TO_JSVAL(JS_NewStringCopyZ(cx, c_str((string)val))); - } - case value::Bool: { - return BOOLEAN_TO_JSVAL((bool)val); - } - case value::Number: { - return DOUBLE_TO_JSVAL(JS_NewDouble(cx, (double)val)); - } - case value::List: { - if (isJSArray(val)) - return OBJECT_TO_JSVAL(valuesToJSElements(JS_NewArrayObject(cx, 0, NULL), val, 0, cx)); - return OBJECT_TO_JSVAL(valuesToJSProperties(JS_NewObject(cx, NULL, NULL, NULL), val, cx)); - } - default: { - return JSVAL_VOID; - } - } -} - -/** - * Converts a list of values to JS properties. - */ -JSObject* valuesToJSProperties(JSObject* o, const list<value>& l, const JSONContext& cx) { - if (isNil(l)) - return o; - - // Write an attribute - const value token(car(l)); - - if (isTaggedList(token, attribute)) { - jsval pv = valueToJSVal(attributeValue(token), cx); - JS_SetProperty(cx, o, c_str(atsign + string(attributeName(token))), &pv); - - } else if (isTaggedList(token, element)) { - - // Write the value of an element - if (elementHasValue(token)) { - jsval pv = valueToJSVal(elementValue(token), cx); - JS_SetProperty(cx, o, c_str(string(elementName(token))), &pv); - - } else { - - // Write a parent element - JSObject* child = JS_NewObject(cx, NULL, NULL, NULL); - jsval pv = OBJECT_TO_JSVAL(child); - JS_SetProperty(cx, o, c_str(string(elementName(token))), &pv); - - // Write its children - valuesToJSProperties(child, elementChildren(token), cx); - } - } - - // Go on - return valuesToJSProperties(o, cdr(l), cx); + return list<value>(js::jsValToValue(val, cx)); } /** @@ -323,9 +72,9 @@ JSObject* valuesToJSProperties(JSObject* o, const list<value>& l, const JSONCont */ template<typename R> class WriteContext { public: - WriteContext(const lambda<R(const string&, const R)>& reduce, const R& accum, const JSONContext& cx) : cx(cx), reduce(reduce), accum(accum) { + WriteContext(const lambda<R(const string&, const R)>& reduce, const R& accum, const js::JSContext& cx) : cx(cx), reduce(reduce), accum(accum) { } - const JSONContext& cx; + const js::JSContext& cx; const lambda<R(const string&, const R)> reduce; R accum; }; @@ -343,7 +92,7 @@ template<typename R> JSBool writeCallback(const jschar *buf, uint32 len, void *d /** * Convert a list of values to a JSON document. */ -template<typename R> const failable<R> writeJSON(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& l, const JSONContext& cx) { +template<typename R> const failable<R> writeJSON(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& l, const js::JSContext& cx) { jsval val = OBJECT_TO_JSVAL(valuesToJSProperties(JS_NewObject(cx, NULL, NULL, NULL), l, cx)); WriteContext<R> wcx(reduce, initial, cx); @@ -355,7 +104,7 @@ template<typename R> const failable<R> writeJSON(const lambda<R(const string&, c /** * Convert a list of values to a list of strings representing a JSON document. */ -const failable<list<string> > writeJSON(const list<value>& l, const JSONContext& cx) { +const failable<list<string> > writeJSON(const list<value>& l, const js::JSContext& cx) { const failable<list<string> > ls = writeJSON<list<string>>(rcons<string>, list<string>(), l, cx); if (!hasContent(ls)) return ls; @@ -365,7 +114,7 @@ const failable<list<string> > writeJSON(const list<value>& l, const JSONContext& /** * Convert a list of function + params to a JSON-RPC request. */ -const failable<list<string> > jsonRequest(const value& id, const value& func, const value& params, json::JSONContext& cx) { +const failable<list<string> > jsonRequest(const value& id, const value& func, const value& params, js::JSContext& cx) { const list<value> r = mklist<value>(mklist<value>("id", id), mklist<value>("method", string(func)), mklist<value>("params", params)); return writeJSON(valuesToElements(r), cx); } @@ -373,20 +122,20 @@ const failable<list<string> > jsonRequest(const value& id, const value& func, co /** * Convert a value to a JSON-RPC result. */ -const failable<list<string> > jsonResult(const value& id, const value& val, JSONContext& cx) { +const failable<list<string> > jsonResult(const value& id, const value& val, js::JSContext& cx) { return writeJSON(valuesToElements(mklist<value>(mklist<value>("id", id), mklist<value>("result", val))), cx); } /** * Convert a JSON-RPC result to a value. */ -const failable<value> jsonResultValue(const list<string>& s, JSONContext& cx) { +const failable<value> jsonResultValue(const list<string>& s, js::JSContext& cx) { const failable<list<value> > jsres = json::readJSON(s, cx); if (!hasContent(jsres)) return mkfailure<value>(reason(jsres)); const list<value> rval(cadr<value>(elementsToValues(content(jsres)))); const value val = cadr(rval); - if (isList(val) && !isJSArray(val)) + if (isList(val) && !js::isJSArray(val)) return value(mklist<value>(val)); return val; } |