Code

Start shell. Begin to make prototypes and wrappers.
authorishmal <ishmal@users.sourceforge.net>
Tue, 29 Aug 2006 09:56:23 +0000 (09:56 +0000)
committerishmal <ishmal@users.sourceforge.net>
Tue, 29 Aug 2006 09:56:23 +0000 (09:56 +0000)
src/dom/Makefile.mingw
src/dom/jsbind.cpp
src/dom/jsengine.cpp
src/dom/jsengine.h
src/dom/work/testjs.cpp [new file with mode: 0644]

index c752dfc8ed779a93672eb3ca6d9a164d8cb4e7ac..2c2dd1c987eb84375ccf29baa5ca2851ca0645f5 100644 (file)
@@ -296,7 +296,7 @@ work/testzip.o
 
 OBJ = $(DOMOBJ) $(JSOBJ)
 
-all: testdom.exe testhttp.exe testodf.exe \
+all: testdom.exe testhttp.exe testjs.exe \
 testsvg.exe testuri.exe testxpath.exe testzip.exe
 
 testdom.exe: libdom.a work/testdom.o
@@ -305,6 +305,9 @@ testdom.exe: libdom.a work/testdom.o
 testhttp.exe: libdom.a work/testhttp.o
        $(CXX) -o $@ work/testhttp.o libdom.a $(LIBS)
 
+testjs.exe: libdom.a work/testjs.o
+       $(CXX) -o $@ work/testjs.o libdom.a $(LIBS)
+
 testodf.exe: libdom.a work/testodf.o
        $(CXX) -o $@ work/testodf.o libdom.a $(LIBS)
 
@@ -335,8 +338,8 @@ clean:
        -$(RM) *.gch
        -$(RM) testdom
        -$(RM) testdom.exe
-       -$(RM) testodf
-       -$(RM) testodf.exe
+       -$(RM) testjs
+       -$(RM) testjs.exe
        -$(RM) testsvg
        -$(RM) testsvg.exe
        -$(RM) testuri
index 60d7adadcfaef4f3d603f9a42cb8061d1d166923..4e2af1dec2aa7188c1e77ce5f81a20e27a6012d5 100644 (file)
@@ -1674,10 +1674,11 @@ public:
         }
 
 
+    static JSClass classDef;
+
 private:
 
     // Standard JS Binding fields
-    static JSClass classDef;
     static JSPropertySpec properties[];
     enum
         {
@@ -5345,11 +5346,38 @@ JSFunctionSpec ECMA_ProcessingInstruction::methods[] =
 
 bool JavascriptEngine::createClasses()
 {
-
+    nodeProto =
+            ECMA_Node::JSInit(cx, globalObj);
+    characterDataProto =
+            ECMA_CharacterData::JSInit(cx, globalObj, nodeProto);
+    textProto =
+            ECMA_Text::JSInit(cx, globalObj, characterDataProto);
+    cdataProto =
+            ECMA_CDATASection::JSInit(cx, globalObj, textProto);
+    documentProto =
+            ECMA_CDATASection::JSInit(cx, globalObj, cdataProto);
     return true;
 }
 
 
+JSObject *JavascriptEngine::wrapDocument(const Document *doc)
+{
+    if (!doc)
+        {
+        error("wrapDocument: null document parameter");
+        return NULL;
+        }
+
+    JSObject *jsdoc = JS_NewObject(cx, &ECMA_Document::classDef,
+                    documentProto, NULL);
+
+    //Wrap around the document...  done!
+    JS_SetPrivate(cx, jsdoc, (void *)doc);
+    
+    return jsdoc;
+}
+
+
 } // namespace dom
 } // namespace w3c
 } // namespace org
index 598682aa7029a69afcc17dff7d9927c11a9ee739..c3c017dc6954518a18201abaccebb2657626f93b 100644 (file)
@@ -78,6 +78,47 @@ static JSClass globalClass =
 };
 
 
+//A couple of shell functions from js.c
+static JSBool shellf_version(JSContext *cx, JSObject *obj,
+            uintN argc, jsval *argv, jsval *rval)
+{
+    if (argc > 0 && JSVAL_IS_INT(argv[0]))
+        *rval = INT_TO_JSVAL(JS_SetVersion(cx, (JSVersion) JSVAL_TO_INT(argv[0])));
+    else
+        *rval = INT_TO_JSVAL(JS_GetVersion(cx));
+    return JS_TRUE;
+}
+
+
+static JSBool shellf_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;
+        fprintf(stdout, "%s%s", i ? " " : "", JS_GetStringBytes(str));
+        }
+    n++;
+    if (n)
+        fputc('\n', stdout);
+    return JS_TRUE;
+}
+
+
+static JSFunctionSpec shell_functions[] =
+{
+    {"version",  shellf_version,   0},
+    {"print",    shellf_print,     0},
+    { 0 }
+};
+
+
+
 bool JavascriptEngine::startup()
 {
     /* You need a runtime and one or more contexts to do anything with JS. */
@@ -94,6 +135,12 @@ bool JavascriptEngine::startup()
         error("can't create JavaScript context");
         return false;
         }
+        
+    JS_SetContextPrivate(cx, (void *)this);
+    
+    
+    JS_SetErrorReporter(cx, errorReporter);
+
     /*
      * The context definitely wants a global object, in order to have standard
      * classes and functions like Date and parseInt.  See below for details on
@@ -101,10 +148,27 @@ bool JavascriptEngine::startup()
      */
 
     globalObj = JS_NewObject(cx, &globalClass, 0, 0);
-    JS_InitStandardClasses(cx, globalObj);
+    if (!globalObj)
+        {
+        error("Could not init global object");
+        return false;
+        }
+    
+    if (!JS_InitStandardClasses(cx, globalObj))
+        {
+        error("Could not init standard classes");
+        return false;
+        }
+
+    if (!JS_DefineFunctions(cx, globalObj, shell_functions))
+        {
+        error("Could not add extra functions");
+        return false;
+        }
 
     if (!createClasses())
         {
+        error("Could not create local classes");
         return false;
         }
         
@@ -121,6 +185,65 @@ bool JavascriptEngine::shutdown()
 }
 
 
+/**
+ *  Evaluate a script
+ */
+bool JavascriptEngine::evaluate(const DOMString &script)
+{
+    const char *cscript = script.c_str();
+    int length    = script.size();
+    jsval rval;
+    JSBool ret = JS_EvaluateScript(cx, globalObj,
+         cscript, length, "buffer",
+         0, &rval);
+
+    if (ret == JS_FALSE)
+        {
+        return false;
+        }
+        
+    return true;
+}
+
+/**
+ *  Evaluate a script from a file
+ */
+bool JavascriptEngine::evaluateFile(const DOMString &fileName)
+{
+    FILE *f = fopen(fileName.c_str(), "r");
+    if (!f)
+        {
+        error("Could not open '%s' for reading", fileName.c_str());
+        return false;
+        }
+    DOMString script;
+    while (true)
+        {
+        int ch = fgetc(f);
+        if (ch < 0)
+            break;
+        script.push_back((char)ch);
+        }
+    fclose(f);
+
+    const char *cscript = script.c_str();
+    int length    = script.size();
+    jsval rval;
+    JSBool ret = JS_EvaluateScript(cx, globalObj,
+         cscript, length, fileName.c_str(),
+         0, &rval);
+
+    if (ret == JS_FALSE)
+        {
+        return false;
+        }
+        
+    return true;
+}
+
+
+
+
 } // namespace dom
 } // namespace w3c
 } // namespace org
index 8b775c98bffd5ef61dbb71caa8349456f34d0b12..3f63c60607786412a2dd1923ba47f1bd4344f0c1 100644 (file)
@@ -30,6 +30,7 @@
  */
 
 
+#include "dom.h"
 #include "js/jsapi.h"
 
 
@@ -52,25 +53,29 @@ public:
      *  Constructor
      */
     JavascriptEngine()
-        { init(); }
+        { startup(); }
+
 
     /**
-     *  Copy constructor
+     *  Destructor
      */
-    JavascriptEngine(const JavascriptEngine &other)
-        { assign(other); }
+    virtual ~JavascriptEngine()
+        { shutdown(); }
 
     /**
-     *  Assignment operator
+     *  Evaluate a script
      */
-    JavascriptEngine &operator=(const JavascriptEngine &other)
-        { assign(other); return *this; }
+    bool evaluate(const DOMString &script);
 
     /**
-     *  Destructor
+     *  Evaluate a script from a file
      */
-    virtual ~JavascriptEngine()
-        {}
+    bool evaluateFile(const DOMString &script);
+
+
+    JSObject *wrapDocument(const Document *doc);
+
+private:
 
     /**
      *  Startup the javascript engine
@@ -82,10 +87,6 @@ public:
      */
     bool shutdown();
 
-
-
-private:
-
     void init()
         {
         rt        = NULL;
@@ -93,6 +94,13 @@ private:
         globalObj = NULL;
         }
     
+    /**
+     *  Assignment operator.  Let's keep this private for now,
+     *  as we want one Spidermonkey runtime per c++ shell     
+     */
+    JavascriptEngine &operator=(const JavascriptEngine &other)
+        { assign(other); return *this; }
+
     void assign(const JavascriptEngine &other)
         {
         rt        = other.rt;
@@ -121,6 +129,20 @@ private:
 
     JSObject *globalObj;
 
+    static void errorReporter(JSContext *cx,
+        const char *message, JSErrorReport *report)
+        {
+        JavascriptEngine *engine = 
+               (JavascriptEngine *) JS_GetContextPrivate(cx);
+        engine->error((char *)message);
+        }
+
+    JSObject *nodeProto;
+    JSObject *characterDataProto;
+    JSObject *textProto;
+    JSObject *cdataProto;
+    JSObject *documentProto;
+
 };
 
 
diff --git a/src/dom/work/testjs.cpp b/src/dom/work/testjs.cpp
new file mode 100644 (file)
index 0000000..7532da4
--- /dev/null
@@ -0,0 +1,129 @@
+/**
+ * Phoebe DOM Implementation.
+ *
+ * This is a C++ approximation of the W3C DOM model, which follows
+ * fairly closely the specifications in the various .idl files, copies of
+ * which are provided for reference.  Most important is this one:
+ *
+ * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/idl-definitions.html
+ *
+ * Authors:
+ *   Bob Jamison
+ *
+ * Copyright (C) 2005 Bob Jamison
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+
+#include "jsengine.h"
+#include "lsimpl.h"
+
+using namespace org::w3c::dom;
+
+
+bool doTest1()
+{
+
+    char *filename = "test.xml";
+    ls::DOMImplementationLSImpl domImpl;
+    ls::LSInput input  = domImpl.createLSInput();
+    ls::LSParser &parser = domImpl.createLSParser(0, "");
+
+    DOMString buf;
+    FILE *f = fopen(filename, "rb");
+    if (!f)
+        {
+        printf("Cannot open %s for reading\n", filename);
+        return false;
+        }
+    while (!feof(f))
+        {
+        int ch = fgetc(f);
+        buf.push_back(ch);
+        }
+    fclose(f);
+    input.setStringData(buf);
+
+    printf("######## PARSE ######################################\n");
+    Document *doc = parser.parse(input);
+
+    if (!doc)
+        {
+        printf("parsing failed\n");
+        return 0;
+        }
+
+    //### OUTPUT
+    printf("######## SERIALIZE ##################################\n");
+    ls::LSSerializer &serializer = domImpl.createLSSerializer();
+    ls::LSOutput output = domImpl.createLSOutput();
+    io::StdWriter writer;
+    output.setCharacterStream(&writer);
+    serializer.write(doc, output);
+
+    printf("####### Namespace check\n");
+    DOMString svgNamespace = "http://www.w3.org/2000/svg";
+    NodeList list = doc->getElementsByTagNameNS(svgNamespace, "svg");
+    int nodeCount = list.getLength();
+    printf("Nodes:%d\n", nodeCount);
+    for (int i=0; i<nodeCount ; i++)
+        {
+        Node *node = list.item(i);
+        serializer.write(node, output);
+        }
+
+    delete doc;
+    return true;
+}
+
+
+bool doTest2()
+{
+    JavascriptEngine js;
+    bool ret = js.evaluate("print(3 * 5);");
+    if (!ret)
+        return false;
+
+    ret = js.evaluate("var s = new CDATASection();");
+    if (!ret)
+        return false;
+        
+    return true;
+}
+
+
+
+
+bool doTests()
+{
+    //if (!doTest1())
+    //    return false;
+    if (!doTest2())
+        return false;
+    return true;
+}
+
+
+int main(int argc, char **argv)
+{
+    if (!doTests())
+        return 1;
+    return 0;
+}
+
+
+