1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include <jsapi.h> 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkJS.h" 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkString.h" 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef _WIN32_WCE 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comextern "C" { 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void abort() { 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0); 198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned int _control87(unsigned int _new, unsigned int mask ) { 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0); 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com time_t mktime(struct tm *timeptr ) { 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0); 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// int errno; 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com char *strdup(const char *) { 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0); 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com char *strerror(int errnum) { 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0); 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int isatty(void* fd) { 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0); 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int putenv(const char *envstring) { 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0); 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com char *getenv(const char *varname) { 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0); 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime) { 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0); 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com struct tm * localtime(const time_t *timer) { 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0); 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size_t strftime(char *strDest, size_t maxsize, const char *format, 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const struct tm *timeptr ) { 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0); 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic JSBool 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comglobal_enumerate(JSContext *cx, JSObject *obj) 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef LAZY_STANDARD_CLASSES 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return JS_EnumerateStandardClasses(cx, obj); 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return JS_TRUE; 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic JSBool 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comglobal_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, JSObject **objp) 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef LAZY_STANDARD_CLASSES 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((flags & JSRESOLVE_ASSIGNING) == 0) { 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com JSBool resolved; 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!JS_ResolveStandardClass(cx, obj, id, &resolved)) 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return JS_FALSE; 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (resolved) { 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *objp = obj; 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return JS_TRUE; 988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if defined(SHELL_HACK) && defined(DEBUG) && defined(XP_UNIX) 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((flags & (JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING)) == 0) { 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * Do this expensive hack only for unoptimized Unix builds, which are 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * not used for benchmarking. 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com char *path, *comp, *full; 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char *name; 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com JSBool ok, found; 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com JSFunction *fun; 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!JSVAL_IS_STRING(id)) 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return JS_TRUE; 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path = getenv("PATH"); 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!path) 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return JS_TRUE; 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path = JS_strdup(cx, path); 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!path) 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return JS_FALSE; 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com name = JS_GetStringBytes(JSVAL_TO_STRING(id)); 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ok = JS_TRUE; 1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (comp = strtok(path, ":"); comp; comp = strtok(NULL, ":")) { 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (*comp != '\0') { 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com full = JS_smprintf("%s/%s", comp, name); 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!full) { 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com JS_ReportOutOfMemory(cx); 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ok = JS_FALSE; 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com full = (char *)name; 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com found = (access(full, X_OK) == 0); 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (*comp != '\0') 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com free(full); 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (found) { 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fun = JS_DefineFunction(cx, obj, name, Exec, 0, JSPROP_ENUMERATE); 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ok = (fun != NULL); 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (ok) 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *objp = obj; 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com JS_free(cx, path); 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return ok; 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return JS_TRUE; 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comJSClass global_class = { 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com "global", JSCLASS_NEW_RESOLVE, 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com JS_PropertyStub, JS_PropertyStub, 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com JS_PropertyStub, JS_PropertyStub, 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com global_enumerate, (JSResolveOp) global_resolve, 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com JS_ConvertStub, JS_FinalizeStub 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkJS::SkJS(void* hwnd) : SkOSWindow(hwnd) { 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((fRuntime = JS_NewRuntime(0x100000)) == NULL) { 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0); 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((fContext = JS_NewContext(fRuntime, 0x1000)) == NULL) { 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0); 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ; 1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((fGlobal = JS_NewObject(fContext, &global_class, NULL, NULL)) == NULL) { 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0); 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (JS_InitStandardClasses(fContext, fGlobal) == NULL) { 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0); 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com setConfig(SkBitmap::kARGB32_Config); 1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com updateSize(); 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com setVisibleP(true); 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com InitializeDisplayables(getBitmap(), fContext, fGlobal, NULL); 1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkJS::~SkJS() { 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DisposeDisplayables(); 1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com JS_DestroyContext(fContext); 1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com JS_DestroyRuntime(fRuntime); 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com JS_ShutDown(); 1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBool SkJS::EvaluateScript(const char* script, jsval* rVal) { 1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return JS_EvaluateScript(fContext, fGlobal, script, strlen(script), 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com "memory" /* no file name */, 0 /* no line number */, rVal); 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBool SkJS::ValueToString(jsval value, SkString* string) { 1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com JSString* str = JS_ValueToString(fContext, value); 1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (str == NULL) 2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com string->set(JS_GetStringBytes(str)); 2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkJS::Test(void* hwnd) { 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkJS js(hwnd); 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com jsval val; 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBool success = js.EvaluateScript("22/7", &val); 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(success); 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkString string; 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com success = js.ValueToString(val, &string); 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(success); 2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(strcmp(string.c_str(), "3.142857142857143") == 0); 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com success = js.EvaluateScript( 2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com "var rect = new rectangle();" 2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com "rect.left = 4;" 2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com "rect.top = 10;" 2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com "rect.right = 20;" 2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com "rect.bottom = 30;" 2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com "rect.width = rect.height + 20;" 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com "rect.draw();" 2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com , &val); 2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(success); 2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com success = js.ValueToString(val, &string); 2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(success); 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endifASSERT(success); 229