From 2b367d9f7599e2fd122e9bb369dbdb8c346323d4 Mon Sep 17 00:00:00 2001 From: ishmal Date: Tue, 29 Aug 2006 09:56:23 +0000 Subject: [PATCH] Start shell. Begin to make prototypes and wrappers. --- src/dom/Makefile.mingw | 9 ++- src/dom/jsbind.cpp | 32 +++++++++- src/dom/jsengine.cpp | 125 +++++++++++++++++++++++++++++++++++++- src/dom/jsengine.h | 50 +++++++++++----- src/dom/work/testjs.cpp | 129 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 325 insertions(+), 20 deletions(-) create mode 100644 src/dom/work/testjs.cpp diff --git a/src/dom/Makefile.mingw b/src/dom/Makefile.mingw index c752dfc8e..2c2dd1c98 100644 --- a/src/dom/Makefile.mingw +++ b/src/dom/Makefile.mingw @@ -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 diff --git a/src/dom/jsbind.cpp b/src/dom/jsbind.cpp index 60d7adadc..4e2af1dec 100644 --- a/src/dom/jsbind.cpp +++ b/src/dom/jsbind.cpp @@ -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 diff --git a/src/dom/jsengine.cpp b/src/dom/jsengine.cpp index 598682aa7..c3c017dc6 100644 --- a/src/dom/jsengine.cpp +++ b/src/dom/jsengine.cpp @@ -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 diff --git a/src/dom/jsengine.h b/src/dom/jsengine.h index 8b775c98b..3f63c6060 100644 --- a/src/dom/jsengine.h +++ b/src/dom/jsengine.h @@ -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 index 000000000..7532da423 --- /dev/null +++ b/src/dom/work/testjs.cpp @@ -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