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