1 /**
2 * Phoebe DOM Implementation.
3 *
4 * This is a C++ approximation of the W3C DOM model, which follows
5 * fairly closely the specifications in the various .idl files, copies of
6 * which are provided for reference. Most important is this one:
7 *
8 * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/idl-definitions.html
9 *
10 * Authors:
11 * Bob Jamison
12 *
13 * Copyright (C) 2006 Bob Jamison
14 *
15 * This library is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU Lesser General Public
17 * License as published by the Free Software Foundation; either
18 * version 2.1 of the License, or (at your option) any later version.
19 *
20 * This library is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * Lesser General Public License for more details.
24 *
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 */
31 #include "jsengine.h"
32 #include "jsdombind.h"
34 #include <stdio.h>
35 #include <stdarg.h>
37 namespace org
38 {
39 namespace w3c
40 {
41 namespace dom
42 {
46 //########################################################################
47 //# M E S S A G E S
48 //########################################################################
49 void JavascriptEngine::error(char *fmt, ...)
50 {
51 va_list args;
52 va_start(args, fmt);
53 fprintf(stderr, "JS error: ");
54 vfprintf(stderr, fmt, args);
55 fprintf(stderr, "\n");
56 va_end(args);
57 }
60 void JavascriptEngine::trace(char *fmt, ...)
61 {
62 va_list args;
63 va_start(args, fmt);
64 fprintf(stdout, "JS: ");
65 vfprintf(stdout, fmt, args);
66 fprintf(stdout, "\n");
67 va_end(args);
68 }
72 static JSClass globalClass =
73 {
74 "Global", 0,
75 JS_PropertyStub, JS_PropertyStub,
76 JS_PropertyStub, JS_PropertyStub,
77 JS_EnumerateStub, JS_ResolveStub,
78 JS_ConvertStub, JS_FinalizeStub
79 };
82 //A couple of shell functions from js.c
83 static JSBool shellf_version(JSContext *cx, JSObject *obj,
84 uintN argc, jsval *argv, jsval *rval)
85 {
86 if (argc > 0 && JSVAL_IS_INT(argv[0]))
87 *rval = INT_TO_JSVAL(JS_SetVersion(cx, (JSVersion) JSVAL_TO_INT(argv[0])));
88 else
89 *rval = INT_TO_JSVAL(JS_GetVersion(cx));
90 return JS_TRUE;
91 }
94 static JSBool shellf_print(JSContext *cx, JSObject *obj,
95 uintN argc, jsval *argv, jsval *rval)
96 {
97 uintN i, n;
98 JSString *str;
100 for (i = n = 0; i < argc; i++)
101 {
102 str = JS_ValueToString(cx, argv[i]);
103 if (!str)
104 return JS_FALSE;
105 fprintf(stdout, "%s%s", i ? " " : "", JS_GetStringBytes(str));
106 }
107 n++;
108 if (n)
109 fputc('\n', stdout);
110 return JS_TRUE;
111 }
114 static JSFunctionSpec shell_functions[] =
115 {
116 {"version", shellf_version, 0},
117 {"print", shellf_print, 0},
118 { 0 }
119 };
123 bool JavascriptEngine::startup()
124 {
125 /* You need a runtime and one or more contexts to do anything with JS. */
126 rt = JS_NewRuntime(0x400000L);
127 if (!rt)
128 {
129 error("can't create JavaScript runtime");
130 return false;
131 }
133 cx = JS_NewContext(rt, 8192);
134 if (!cx)
135 {
136 error("can't create JavaScript context");
137 return false;
138 }
140 JS_SetContextPrivate(cx, (void *)this);
143 JS_SetErrorReporter(cx, errorReporter);
145 /*
146 * The context definitely wants a global object, in order to have standard
147 * classes and functions like Date and parseInt. See below for details on
148 * JS_NewObject.
149 */
151 globalObj = JS_NewObject(cx, &globalClass, 0, 0);
152 if (!globalObj)
153 {
154 error("Could not init global object");
155 return false;
156 }
158 if (!JS_InitStandardClasses(cx, globalObj))
159 {
160 error("Could not init standard classes");
161 return false;
162 }
164 if (!JS_DefineFunctions(cx, globalObj, shell_functions))
165 {
166 error("Could not add extra functions");
167 return false;
168 }
170 if (!createClasses())
171 {
172 error("Could not create local classes");
173 return false;
174 }
176 return true;
177 }
182 bool JavascriptEngine::shutdown()
183 {
185 return true;
186 }
189 /**
190 * Evaluate a script
191 */
192 bool JavascriptEngine::evaluate(const DOMString &script)
193 {
194 const char *cscript = script.c_str();
195 int length = script.size();
196 jsval rval;
197 JSBool ret = JS_EvaluateScript(cx, globalObj,
198 cscript, length, "buffer",
199 0, &rval);
201 if (ret == JS_FALSE)
202 {
203 return false;
204 }
206 return true;
207 }
209 /**
210 * Evaluate a script from a file
211 */
212 bool JavascriptEngine::evaluateFile(const DOMString &fileName)
213 {
214 FILE *f = fopen(fileName.c_str(), "r");
215 if (!f)
216 {
217 error("Could not open '%s' for reading", fileName.c_str());
218 return false;
219 }
220 DOMString script;
221 while (true)
222 {
223 int ch = fgetc(f);
224 if (ch < 0)
225 break;
226 script.push_back((char)ch);
227 }
228 fclose(f);
230 const char *cscript = script.c_str();
231 int length = script.size();
232 jsval rval;
233 JSBool ret = JS_EvaluateScript(cx, globalObj,
234 cscript, length, fileName.c_str(),
235 0, &rval);
237 if (ret == JS_FALSE)
238 {
239 return false;
240 }
242 return true;
243 }
245 /**
246 * Bind with the basic DOM classes
247 */
248 bool JavascriptEngine::createClasses()
249 {
250 JavascriptDOMBinder binder(*this);
251 binder.createClasses();
252 return true;
253 }
257 } // namespace dom
258 } // namespace w3c
259 } // namespace org
262 //########################################################################
263 //# E N D O F F I L E
264 //########################################################################