blob: 03ccba6c3596e5cf1d2e7e26fea9705d8e48fd9b [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/* libs/graphics/xml/SkJS.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include <jsapi.h>
19
20#include "SkJS.h"
21#include "SkString.h"
22
23#ifdef _WIN32_WCE
24extern "C" {
25 void abort() {
26 SkASSERT(0);
27 }
28
29 unsigned int _control87(unsigned int _new, unsigned int mask ) {
30 SkASSERT(0);
31 return 0;
32 }
33
34 time_t mktime(struct tm *timeptr ) {
35 SkASSERT(0);
36 return 0;
37 }
38
39// int errno;
40
41 char *strdup(const char *) {
42 SkASSERT(0);
43 return 0;
44 }
45
46 char *strerror(int errnum) {
47 SkASSERT(0);
48 return 0;
49 }
50
51 int isatty(void* fd) {
52 SkASSERT(0);
53 return 0;
54 }
55
56 int putenv(const char *envstring) {
57 SkASSERT(0);
58 return 0;
59 }
60
61 char *getenv(const char *varname) {
62 SkASSERT(0);
63 return 0;
64 }
65
66 void GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime) {
67 SkASSERT(0);
68 }
69
70 struct tm * localtime(const time_t *timer) {
71 SkASSERT(0);
72 return 0;
73 }
74
75 size_t strftime(char *strDest, size_t maxsize, const char *format,
76 const struct tm *timeptr ) {
77 SkASSERT(0);
78 return 0;
79 }
80
81}
82#endif
83
84static JSBool
85global_enumerate(JSContext *cx, JSObject *obj)
86{
87#ifdef LAZY_STANDARD_CLASSES
88 return JS_EnumerateStandardClasses(cx, obj);
89#else
90 return JS_TRUE;
91#endif
92}
93
94static JSBool
95global_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, JSObject **objp)
96{
97#ifdef LAZY_STANDARD_CLASSES
98 if ((flags & JSRESOLVE_ASSIGNING) == 0) {
99 JSBool resolved;
100
101 if (!JS_ResolveStandardClass(cx, obj, id, &resolved))
102 return JS_FALSE;
103 if (resolved) {
104 *objp = obj;
105 return JS_TRUE;
106 }
107 }
108#endif
109
110#if defined(SHELL_HACK) && defined(DEBUG) && defined(XP_UNIX)
111 if ((flags & (JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING)) == 0) {
112 /*
113 * Do this expensive hack only for unoptimized Unix builds, which are
114 * not used for benchmarking.
115 */
116 char *path, *comp, *full;
117 const char *name;
118 JSBool ok, found;
119 JSFunction *fun;
120
121 if (!JSVAL_IS_STRING(id))
122 return JS_TRUE;
123 path = getenv("PATH");
124 if (!path)
125 return JS_TRUE;
126 path = JS_strdup(cx, path);
127 if (!path)
128 return JS_FALSE;
129 name = JS_GetStringBytes(JSVAL_TO_STRING(id));
130 ok = JS_TRUE;
131 for (comp = strtok(path, ":"); comp; comp = strtok(NULL, ":")) {
132 if (*comp != '\0') {
133 full = JS_smprintf("%s/%s", comp, name);
134 if (!full) {
135 JS_ReportOutOfMemory(cx);
136 ok = JS_FALSE;
137 break;
138 }
139 } else {
140 full = (char *)name;
141 }
142 found = (access(full, X_OK) == 0);
143 if (*comp != '\0')
144 free(full);
145 if (found) {
146 fun = JS_DefineFunction(cx, obj, name, Exec, 0, JSPROP_ENUMERATE);
147 ok = (fun != NULL);
148 if (ok)
149 *objp = obj;
150 break;
151 }
152 }
153 JS_free(cx, path);
154 return ok;
155 }
156#else
157 return JS_TRUE;
158#endif
159}
160
161JSClass global_class = {
162 "global", JSCLASS_NEW_RESOLVE,
163 JS_PropertyStub, JS_PropertyStub,
164 JS_PropertyStub, JS_PropertyStub,
165 global_enumerate, (JSResolveOp) global_resolve,
166 JS_ConvertStub, JS_FinalizeStub
167};
168
169SkJS::SkJS(void* hwnd) : SkOSWindow(hwnd) {
170 if ((fRuntime = JS_NewRuntime(0x100000)) == NULL) {
171 SkASSERT(0);
172 return;
173 }
174 if ((fContext = JS_NewContext(fRuntime, 0x1000)) == NULL) {
175 SkASSERT(0);
176 return;
177 }
178 ;
179 if ((fGlobal = JS_NewObject(fContext, &global_class, NULL, NULL)) == NULL) {
180 SkASSERT(0);
181 return;
182 }
183 if (JS_InitStandardClasses(fContext, fGlobal) == NULL) {
184 SkASSERT(0);
185 return;
186 }
187 setConfig(SkBitmap::kARGB32_Config);
188 updateSize();
189 setVisibleP(true);
190 InitializeDisplayables(getBitmap(), fContext, fGlobal, NULL);
191}
192
193SkJS::~SkJS() {
194 DisposeDisplayables();
195 JS_DestroyContext(fContext);
196 JS_DestroyRuntime(fRuntime);
197 JS_ShutDown();
198}
199
200SkBool SkJS::EvaluateScript(const char* script, jsval* rVal) {
201 return JS_EvaluateScript(fContext, fGlobal, script, strlen(script),
202 "memory" /* no file name */, 0 /* no line number */, rVal);
203}
204
205SkBool SkJS::ValueToString(jsval value, SkString* string) {
206 JSString* str = JS_ValueToString(fContext, value);
207 if (str == NULL)
208 return false;
209 string->set(JS_GetStringBytes(str));
210 return true;
211}
212
213#ifdef SK_DEBUG
214void SkJS::Test(void* hwnd) {
215 SkJS js(hwnd);
216 jsval val;
217 SkBool success = js.EvaluateScript("22/7", &val);
218 SkASSERT(success);
219 SkString string;
220 success = js.ValueToString(val, &string);
221 SkASSERT(success);
222 SkASSERT(strcmp(string.c_str(), "3.142857142857143") == 0);
223 success = js.EvaluateScript(
224 "var rect = new rectangle();"
225 "rect.left = 4;"
226 "rect.top = 10;"
227 "rect.right = 20;"
228 "rect.bottom = 30;"
229 "rect.width = rect.height + 20;"
230 "rect.draw();"
231 , &val);
232 SkASSERT(success);
233 success = js.ValueToString(val, &string);
234 SkASSERT(success);
235}
236#endifASSERT(success);
237