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
16extern "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
76static JSBool
77global_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
86static JSBool
87global_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
153JSClass 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
161SkJS::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
185SkJS::~SkJS() {
186    DisposeDisplayables();
187    JS_DestroyContext(fContext);
188    JS_DestroyRuntime(fRuntime);
189    JS_ShutDown();
190}
191
192SkBool 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
197SkBool 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
206void 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