|
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" { |
|
17 void abort() { |
|
18 SkASSERT(0); |
|
19 } |
|
20 |
|
21 unsigned int _control87(unsigned int _new, unsigned int mask ) { |
|
22 SkASSERT(0); |
|
23 return 0; |
|
24 } |
|
25 |
|
26 time_t mktime(struct tm *timeptr ) { |
|
27 SkASSERT(0); |
|
28 return 0; |
|
29 } |
|
30 |
|
31 // int errno; |
|
32 |
|
33 char *strdup(const char *) { |
|
34 SkASSERT(0); |
|
35 return 0; |
|
36 } |
|
37 |
|
38 char *strerror(int errnum) { |
|
39 SkASSERT(0); |
|
40 return 0; |
|
41 } |
|
42 |
|
43 int isatty(void* fd) { |
|
44 SkASSERT(0); |
|
45 return 0; |
|
46 } |
|
47 |
|
48 int putenv(const char *envstring) { |
|
49 SkASSERT(0); |
|
50 return 0; |
|
51 } |
|
52 |
|
53 char *getenv(const char *varname) { |
|
54 SkASSERT(0); |
|
55 return 0; |
|
56 } |
|
57 |
|
58 void GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime) { |
|
59 SkASSERT(0); |
|
60 } |
|
61 |
|
62 struct tm * localtime(const time_t *timer) { |
|
63 SkASSERT(0); |
|
64 return 0; |
|
65 } |
|
66 |
|
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 |
|
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 |
|
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 |
|
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 |
|
185 SkJS::~SkJS() { |
|
186 DisposeDisplayables(); |
|
187 JS_DestroyContext(fContext); |
|
188 JS_DestroyRuntime(fRuntime); |
|
189 JS_ShutDown(); |
|
190 } |
|
191 |
|
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 |
|
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 |
|
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); |