Mercurial > spidermonkey-playground
changeset 69:be61430630ab
Separated out some of the TCB-specific code into tcb.cpp/h.
author | Atul Varma <varmaa@toolness.com> |
---|---|
date | Thu, 25 Jun 2009 17:53:28 -0700 |
parents | 293eaba319ac |
children | f6e3733eac01 |
files | pavement.py spidermonkey-playground.cpp tcb.cpp tcb.h |
diffstat | 4 files changed, 273 insertions(+), 239 deletions(-) [+] |
line wrap: on
line diff
--- a/pavement.py Thu Jun 25 12:36:38 2009 -0700 +++ b/pavement.py Thu Jun 25 17:53:28 2009 -0700 @@ -17,6 +17,7 @@ "-g", # produce output for gdb "-DDEBUG", "spidermonkey-playground.cpp", + "tcb.cpp", "wrapper.cpp", "server_socket.cpp", "memory_profiler.cpp",
--- a/spidermonkey-playground.cpp Thu Jun 25 12:36:38 2009 -0700 +++ b/spidermonkey-playground.cpp Thu Jun 25 17:53:28 2009 -0700 @@ -42,6 +42,7 @@ #include "jsapi.h" #include "jsdbgapi.h" +#include "tcb.h" #include "wrapper.h" #include "server_socket.h" #include "memory_profiler.h" @@ -53,41 +54,14 @@ static JSContext *tcb_cx; static JSObject *tcb_global; -// TODO: Make sure we're rooting objects appropriately here so that -// the interpreter doesn't randomly crash or something. - -/* The class of the global object. */ -JSClass global_class = { - "global", JSCLASS_GLOBAL_FLAGS, +// The class of SecurableModules. +static JSClass SM_global_class = { + "SecurableModuleGlobal", JSCLASS_GLOBAL_FLAGS, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, JSCLASS_NO_OPTIONAL_MEMBERS }; -// This native JS function prints the given string to the console. - -static JSBool print(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - char *str; - - if (!JS_ConvertArguments(cx, argc, argv, "s", &str)) - return JS_FALSE; - - printf("%s\n", str); - - return JS_TRUE; -} - -// This native JS function forces garbage collection. - -static JSBool forceGC(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JS_GC(cx); - return JS_TRUE; -} - // This native JS function is an implementation of the SecurableModule // require() function. For more information, see: // @@ -125,7 +99,8 @@ // TODO: Check for return values here. JSContext *module_cx = JS_NewContext(JS_GetRuntime(cx), 8192); JS_BeginRequest(module_cx); - JSObject *module_global = JS_NewObject(module_cx, &global_class, NULL, + JSObject *module_global = JS_NewObject(module_cx, + &SM_global_class, NULL, NULL); JS_InitStandardClasses(module_cx, module_global); JS_DefineProperty(module_cx, module_global, "imports", @@ -151,206 +126,6 @@ return JS_TRUE; } -// This native JS function is a wrapper for JS_Enumerate(). - -static JSBool enumerate(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - JSObject *target; - - if (!JS_ConvertArguments(cx, argc, argv, "o", &target)) - return JS_FALSE; - - JSIdArray *ids = JS_Enumerate(cx, target); - - if (ids == NULL) - return JS_FALSE; - - JSObject *array = JS_NewArrayObject(cx, ids->length, ids->vector); - *rval = OBJECT_TO_JSVAL(array); - return JS_TRUE; -} - -// This native JS function looks up the property of an object, bypassing -// security checks and getters/setters. - -static JSBool lookupProperty(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - JSObject *target; - - if (argc < 2) { - JS_ReportError(cx, "Must provide id to lookup."); - return JS_FALSE; - } - - if (!JS_ConvertArguments(cx, argc, argv, "o", &target)) - return JS_FALSE; - - return JS_LookupPropertyById(cx, target, argv[1], rval); -} - -// This native JS function returns a JS object containing metadata about -// the given function. - -static JSBool functionInfo(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - JSFunction *func; - - if (!JS_ConvertArguments(cx, argc, argv, "f", &func)) - return JS_FALSE; - - JSScript *script = JS_GetFunctionScript(cx, func); - - if (script == NULL) { - *rval = JSVAL_NULL; - return JS_TRUE; - } - - jsval filenameVal = JSVAL_NULL; - - const char *filename = JS_GetScriptFilename(cx, script); - if (filename) { - JSString *filenameStr = JS_NewStringCopyZ(cx, filename); - filenameVal = STRING_TO_JSVAL(filenameStr); - } - - // TODO: Check for return values here. - JSObject *funcInfo = JS_NewObject(cx, NULL, NULL, NULL); - JS_DefineProperty(cx, funcInfo, "filename", filenameVal, - NULL, NULL, 0); - - *rval = OBJECT_TO_JSVAL(funcInfo); - return JS_TRUE; -} - -// This native JS function returns a JS representation of the current -// state of the stack, starting with the callee's stack frame and going -// up from there. - -static JSBool stack(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSAutoLocalRootScope autoScope(cx); - - JSStackFrame *iterator = NULL; - JSStackFrame *frame; - JSObject *prevFrameInfo = NULL; - JSObject *firstFrameInfo = NULL; - bool skippedMyFrame = false; - - if (obj == NULL) - // We're being called from native code, don't skip the topmost frame. - skippedMyFrame = true; - - while ((frame = JS_FrameIterator(cx, &iterator)) != NULL) { - if (!skippedMyFrame) { - skippedMyFrame = true; - continue; - } - - jsval functionNameVal = JSVAL_NULL; - jsval filenameVal = JSVAL_NULL; - jsval lineNoVal = JSVAL_ZERO; - jsval functionObjectVal = JSVAL_NULL; - jsval scopeChainVal = JSVAL_NULL; - - JSFunction *func = JS_GetFrameFunction(cx, frame); - if (func) { - JSString *functionName = JS_GetFunctionId(func); - if (functionName) - functionNameVal = STRING_TO_JSVAL(functionName); - } - - if (!JS_IsNativeFrame(cx, frame)) { - JSScript *script = JS_GetFrameScript(cx, frame); - jsbytecode *bytecode = JS_GetFramePC(cx, frame); - - const char *filename = JS_GetScriptFilename(cx, script); - if (filename) { - JSString *filenameStr = JS_NewStringCopyZ(cx, filename); - filenameVal = STRING_TO_JSVAL(filenameStr); - } - - uintN lineNo = JS_PCToLineNumber(cx, script, bytecode); - lineNoVal = INT_TO_JSVAL(lineNo); - - JSObject *functionObject = JS_GetFrameFunctionObject(cx, frame); - functionObjectVal = OBJECT_TO_JSVAL(functionObject); - - JSObject *scopeChain = JS_GetFrameScopeChain(cx, frame); - scopeChainVal = OBJECT_TO_JSVAL(scopeChain); - } - - // TODO: Check for return values here. - JSObject *frameInfo = JS_NewObject(cx, NULL, NULL, NULL); - JS_DefineProperty(cx, frameInfo, "filename", filenameVal, - NULL, NULL, 0); - JS_DefineProperty(cx, frameInfo, "lineNo", lineNoVal, - NULL, NULL, 0); - JS_DefineProperty(cx, frameInfo, "functionName", functionNameVal, - NULL, NULL, 0); - JS_DefineProperty(cx, frameInfo, "functionObject", functionObjectVal, - NULL, NULL, 0); - JS_DefineProperty(cx, frameInfo, "scopeChain", scopeChainVal, - NULL, NULL, 0); - - if (prevFrameInfo) - JS_DefineProperty(cx, prevFrameInfo, "caller", - OBJECT_TO_JSVAL(frameInfo), NULL, NULL, 0); - else - firstFrameInfo = frameInfo; - - prevFrameInfo = frameInfo; - } - - if (firstFrameInfo) - *rval = OBJECT_TO_JSVAL(firstFrameInfo); - else - *rval = JSVAL_NULL; - - return JS_TRUE; -} - -// Our global hook called whenever an exception is thrown saves the current -// exception and stack information to the 'lastException' and -// 'lastExceptionTraceback' globals of the TCB, respectively, much like -// Python's sys.exc_info(). - -static JSTrapStatus throwHook(JSContext *cx, JSScript *script, jsbytecode *pc, - jsval *rval, void *closure) -{ - JSObject *tcb_global = (JSObject *) closure; - jsval lastExceptionTraceback; - jsval lastException; - - jsval exception = *rval; - if (JS_IsExceptionPending(cx)) - if (!JS_GetPendingException(cx, &exception)) - printf("Getting exception failed.\n"); - - if (!JS_GetProperty(cx, tcb_global, "lastException", &lastException)) - printf("Unable to retrieve last exception."); - - if (lastException == exception) - // The same exception is just propagating through the stack; keep - // our existing last-exception info. - return JSTRAP_CONTINUE; - - if (!stack(cx, NULL, 0, NULL, &lastExceptionTraceback)) { - printf("Generation of exception info failed."); - lastExceptionTraceback = JSVAL_NULL; - } - - if (!JS_SetProperty(cx, tcb_global, "lastExceptionTraceback", - &lastExceptionTraceback) || - !JS_SetProperty(cx, tcb_global, "lastException", &exception)) - printf("Setting of exception info failed."); - - return JSTRAP_CONTINUE; -} - // Our global checkAccess callback just checks to see if a JS function called // 'checkAccess' has been defined in the TCB, and delegates to that if so. If // not, though, we do a default checkAccess. @@ -376,16 +151,16 @@ } static JSFunctionSpec tcb_global_functions[] = { - JS_FS("print", print, 1, 0, 0), + JS_FS("print", TCB_print, 1, 0, 0), + JS_FS("stack", TCB_stack, 0, 0, 0), + JS_FS("lookupProperty", TCB_lookupProperty, 2, 0, 0), + JS_FS("functionInfo", TCB_functionInfo, 1, 0, 0), + JS_FS("enumerate", TCB_enumerate, 1, 0, 0), + JS_FS("forceGC", TCB_forceGC, 0, 0, 0), JS_FS("getWrapper", getWrapper, 1, 0, 0), JS_FS("unwrap", unwrapObject, 1, 0, 0), JS_FS("wrap", wrapObject, 2, 0, 0), - JS_FS("stack", stack, 0, 0, 0), JS_FS("require", require, 2, 0, 0), - JS_FS("lookupProperty", lookupProperty, 2, 0, 0), - JS_FS("functionInfo", functionInfo, 1, 0, 0), - JS_FS("enumerate", enumerate, 1, 0, 0), - JS_FS("forceGC", forceGC, 0, 0, 0), JS_FS("profileMemory", profileMemory, 0, 0, 0), JS_FS("ServerSocket", createServerSocket, 0, 0, 0), JS_FS_END @@ -423,7 +198,7 @@ #endif /* Create the TCB's global object. */ - tcb_global = JS_NewObject(tcb_cx, &global_class, NULL, NULL); + tcb_global = JS_NewObject(tcb_cx, &TCB_global_class, NULL, NULL); if (tcb_global == NULL) return 1; @@ -438,7 +213,7 @@ return 1; // TODO: Check for return values here. - JS_SetThrowHook(rt, throwHook, tcb_global); + JS_SetThrowHook(rt, TCB_throwHook, tcb_global); JS_DefineProperty(tcb_cx, tcb_global, "lastExceptionTraceback", JSVAL_NULL, NULL, NULL, 0); JS_DefineProperty(tcb_cx, tcb_global, "lastException", JSVAL_NULL,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tcb.cpp Thu Jun 25 17:53:28 2009 -0700 @@ -0,0 +1,233 @@ +#include "tcb.h" + +// The class of the global object. +JSClass TCB_global_class = { + "TCBGlobal", JSCLASS_GLOBAL_FLAGS, + JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, + JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, + JSCLASS_NO_OPTIONAL_MEMBERS +}; + +// This native JS function prints the given string to the console. + +JSBool TCB_print(JSContext *cx, JSObject *obj, uintN argc, + jsval *argv, jsval *rval) +{ + char *str; + + if (!JS_ConvertArguments(cx, argc, argv, "s", &str)) + return JS_FALSE; + + printf("%s\n", str); + + return JS_TRUE; +} + +// This native JS function forces garbage collection. + +JSBool TCB_forceGC(JSContext *cx, JSObject *obj, uintN argc, + jsval *argv, jsval *rval) +{ + JS_GC(cx); + return JS_TRUE; +} + +// This native JS function is a wrapper for JS_Enumerate(). + +JSBool TCB_enumerate(JSContext *cx, JSObject *obj, uintN argc, + jsval *argv, jsval *rval) +{ + JSObject *target; + + if (!JS_ConvertArguments(cx, argc, argv, "o", &target)) + return JS_FALSE; + + JSIdArray *ids = JS_Enumerate(cx, target); + + if (ids == NULL) + return JS_FALSE; + + JSObject *array = JS_NewArrayObject(cx, ids->length, ids->vector); + *rval = OBJECT_TO_JSVAL(array); + return JS_TRUE; +} + +// This native JS function looks up the property of an object, bypassing +// security checks and getters/setters. + +JSBool TCB_lookupProperty(JSContext *cx, JSObject *obj, uintN argc, + jsval *argv, jsval *rval) +{ + JSObject *target; + + if (argc < 2) { + JS_ReportError(cx, "Must provide id to lookup."); + return JS_FALSE; + } + + if (!JS_ConvertArguments(cx, argc, argv, "o", &target)) + return JS_FALSE; + + return JS_LookupPropertyById(cx, target, argv[1], rval); +} + +// This native JS function returns a JS object containing metadata about +// the given function. + +JSBool TCB_functionInfo(JSContext *cx, JSObject *obj, uintN argc, + jsval *argv, jsval *rval) +{ + JSFunction *func; + + if (!JS_ConvertArguments(cx, argc, argv, "f", &func)) + return JS_FALSE; + + JSScript *script = JS_GetFunctionScript(cx, func); + + if (script == NULL) { + *rval = JSVAL_NULL; + return JS_TRUE; + } + + jsval filenameVal = JSVAL_NULL; + + const char *filename = JS_GetScriptFilename(cx, script); + if (filename) { + JSString *filenameStr = JS_NewStringCopyZ(cx, filename); + filenameVal = STRING_TO_JSVAL(filenameStr); + } + + // TODO: Check for return values here. + JSObject *funcInfo = JS_NewObject(cx, NULL, NULL, NULL); + JS_DefineProperty(cx, funcInfo, "filename", filenameVal, + NULL, NULL, 0); + + *rval = OBJECT_TO_JSVAL(funcInfo); + return JS_TRUE; +} + +// This native JS function returns a JS representation of the current +// state of the stack, starting with the callee's stack frame and going +// up from there. + +JSBool TCB_stack(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, + jsval *rval) +{ + JSAutoLocalRootScope autoScope(cx); + + JSStackFrame *iterator = NULL; + JSStackFrame *frame; + JSObject *prevFrameInfo = NULL; + JSObject *firstFrameInfo = NULL; + bool skippedMyFrame = false; + + if (obj == NULL) + // We're being called from native code, don't skip the topmost frame. + skippedMyFrame = true; + + while ((frame = JS_FrameIterator(cx, &iterator)) != NULL) { + if (!skippedMyFrame) { + skippedMyFrame = true; + continue; + } + + jsval functionNameVal = JSVAL_NULL; + jsval filenameVal = JSVAL_NULL; + jsval lineNoVal = JSVAL_ZERO; + jsval functionObjectVal = JSVAL_NULL; + jsval scopeChainVal = JSVAL_NULL; + + JSFunction *func = JS_GetFrameFunction(cx, frame); + if (func) { + JSString *functionName = JS_GetFunctionId(func); + if (functionName) + functionNameVal = STRING_TO_JSVAL(functionName); + } + + if (!JS_IsNativeFrame(cx, frame)) { + JSScript *script = JS_GetFrameScript(cx, frame); + jsbytecode *bytecode = JS_GetFramePC(cx, frame); + + const char *filename = JS_GetScriptFilename(cx, script); + if (filename) { + JSString *filenameStr = JS_NewStringCopyZ(cx, filename); + filenameVal = STRING_TO_JSVAL(filenameStr); + } + + uintN lineNo = JS_PCToLineNumber(cx, script, bytecode); + lineNoVal = INT_TO_JSVAL(lineNo); + + JSObject *functionObject = JS_GetFrameFunctionObject(cx, frame); + functionObjectVal = OBJECT_TO_JSVAL(functionObject); + + JSObject *scopeChain = JS_GetFrameScopeChain(cx, frame); + scopeChainVal = OBJECT_TO_JSVAL(scopeChain); + } + + // TODO: Check for return values here. + JSObject *frameInfo = JS_NewObject(cx, NULL, NULL, NULL); + JS_DefineProperty(cx, frameInfo, "filename", filenameVal, + NULL, NULL, 0); + JS_DefineProperty(cx, frameInfo, "lineNo", lineNoVal, + NULL, NULL, 0); + JS_DefineProperty(cx, frameInfo, "functionName", functionNameVal, + NULL, NULL, 0); + JS_DefineProperty(cx, frameInfo, "functionObject", functionObjectVal, + NULL, NULL, 0); + JS_DefineProperty(cx, frameInfo, "scopeChain", scopeChainVal, + NULL, NULL, 0); + + if (prevFrameInfo) + JS_DefineProperty(cx, prevFrameInfo, "caller", + OBJECT_TO_JSVAL(frameInfo), NULL, NULL, 0); + else + firstFrameInfo = frameInfo; + + prevFrameInfo = frameInfo; + } + + if (firstFrameInfo) + *rval = OBJECT_TO_JSVAL(firstFrameInfo); + else + *rval = JSVAL_NULL; + + return JS_TRUE; +} + +// Our global hook called whenever an exception is thrown saves the current +// exception and stack information to the 'lastException' and +// 'lastExceptionTraceback' globals of the TCB, respectively, much like +// Python's sys.exc_info(). + +JSTrapStatus TCB_throwHook(JSContext *cx, JSScript *script, jsbytecode *pc, + jsval *rval, void *closure) +{ + JSObject *tcb_global = (JSObject *) closure; + jsval lastExceptionTraceback; + jsval lastException; + + jsval exception = *rval; + if (JS_IsExceptionPending(cx)) + if (!JS_GetPendingException(cx, &exception)) + printf("Getting exception failed.\n"); + + if (!JS_GetProperty(cx, tcb_global, "lastException", &lastException)) + printf("Unable to retrieve last exception."); + + if (lastException == exception) + // The same exception is just propagating through the stack; keep + // our existing last-exception info. + return JSTRAP_CONTINUE; + + if (!TCB_stack(cx, NULL, 0, NULL, &lastExceptionTraceback)) { + printf("Generation of exception info failed."); + lastExceptionTraceback = JSVAL_NULL; + } + + if (!JS_SetProperty(cx, tcb_global, "lastExceptionTraceback", + &lastExceptionTraceback) || + !JS_SetProperty(cx, tcb_global, "lastException", &exception)) + printf("Setting of exception info failed."); + + return JSTRAP_CONTINUE; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tcb.h Thu Jun 25 17:53:28 2009 -0700 @@ -0,0 +1,25 @@ +#include "jsapi.h" +#include "jsdbgapi.h" + +extern JSClass TCB_global_class; + +extern JSBool TCB_print(JSContext *cx, JSObject *obj, uintN argc, + jsval *argv, jsval *rval); + +extern JSBool TCB_forceGC(JSContext *cx, JSObject *obj, uintN argc, + jsval *argv, jsval *rval); + +extern JSBool TCB_enumerate(JSContext *cx, JSObject *obj, uintN argc, + jsval *argv, jsval *rval); + +extern JSBool TCB_lookupProperty(JSContext *cx, JSObject *obj, uintN argc, + jsval *argv, jsval *rval); + +extern JSBool TCB_functionInfo(JSContext *cx, JSObject *obj, uintN argc, + jsval *argv, jsval *rval); + +extern JSBool TCB_stack(JSContext *cx, JSObject *obj, uintN argc, + jsval *argv, jsval *rval); + +extern JSTrapStatus TCB_throwHook(JSContext *cx, JSScript *script, + jsbytecode *pc, jsval *rval, void *closure);