SkJS.cpp revision 03202c9c3dfbf8c4feb0a1ee9b3680817e633f58
1/* 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
238