void CThreadDebugger::DestroyScriptHook(JSContext* cx, JSScript* script) { uint scriptExtent = JS_GetScriptLineExtent (cx, script); uint baseLine = JS_GetScriptBaseLineNumber(cx, script); char* pStr = NULL; pStr = (char*)JS_GetScriptFilename(cx, script); if (pStr != NULL) { std::string fileName(pStr); for (uint line = baseLine; line < scriptExtent + baseLine; ++line) { if (CheckIfMappingPresent(fileName, line)) { if (m->m_LineToPCMap[fileName][line].pScript == script) { ReturnActiveBreakPoints(m->m_LineToPCMap[fileName][line].pBytecode); m->m_LineToPCMap[fileName].erase(line); if (m->m_LineToPCMap[fileName].empty()) m->m_LineToPCMap.erase(fileName); } } } } }
unsigned jsd_GetScriptLineExtent(JSDContext* jsdc, JSDScript *jsdscript) { if( NOT_SET_YET == (int)jsdscript->lineExtent ) jsdscript->lineExtent = JS_GetScriptLineExtent(jsdc->dumbContext, jsdscript->script); return jsdscript->lineExtent; }
void CThreadDebugger::NewScriptHook(JSContext* cx, const char* filename, unsigned lineno, JSScript* script, JSFunction* UNUSED(fun), void* UNUSED(callerdata)) { uint scriptExtent = JS_GetScriptLineExtent (cx, script); std::string stringFileName(filename); if (stringFileName == "") return; for (uint line = lineno; line < scriptExtent + lineno; ++line) { // If we already have a mapping for this line, we check if the current scipt is more deeply nested. // If it isn't more deeply nested, we don't overwrite the previous mapping // The most deeply nested script is always the one that must be used! uint firstLine = 0; uint lastLine = 0; jsbytecode* oldPC = NULL; if (CheckIfMappingPresent(stringFileName, line)) { firstLine = m->m_LineToPCMap[stringFileName][line].firstLineInFunction; lastLine = m->m_LineToPCMap[stringFileName][line].lastLineInFunction; // If an entry nested equally is present too, we must overwrite it. // The same script(function) can trigger a NewScriptHook multiple times without DestroyScriptHooks between these // calls. In this case the old script becomes invalid. if (lineno < firstLine || scriptExtent + lineno > lastLine) continue; else oldPC = m->m_LineToPCMap[stringFileName][line].pBytecode; } jsbytecode* pc = JS_LineNumberToPC (cx, script, line); m->m_LineToPCMap[stringFileName][line].pBytecode = pc; m->m_LineToPCMap[stringFileName][line].pScript = script; m->m_LineToPCMap[stringFileName][line].firstLineInFunction = lineno; m->m_LineToPCMap[stringFileName][line].lastLineInFunction = lineno + scriptExtent; // If we are replacing a script, the associated traps become invalid if (lineno == firstLine && scriptExtent + lineno == lastLine) { ReturnActiveBreakPoints(oldPC); SetAllNewTraps(); } } }
nsresult leakmonJSObjectInfo::Init(leakmonObjectsInReportTable &aObjectsInReport) { mIsInitialized = PR_TRUE; JSContext *cx = leakmonService::GetJSContext(); NS_ENSURE_TRUE(cx, NS_ERROR_UNEXPECTED); JSAutoRequest ar(cx); if (!JSVAL_IS_PRIMITIVE(mJSValue)) { JSObject *obj = JSVAL_TO_OBJECT(mJSValue); // All of the objects in obj's prototype chain, and all // objects reachable from JS_NewPropertyIterator should // (I think?) be in the same compartment. JSAutoEnterCompartment ac; if (!ac.enter(cx, obj)) { return NS_ERROR_FAILURE; } JSObject *p; for (p = obj; p; p = JS_GetPrototype(cx, p)) { // Stack-scanning protects newly-created objects // (etor) from GC. (And protecting |etor| // should in turn protect |id|.) // JS_NewPropertyIterator has the nice property that it // avoids JS_Enumerate on native objects (where it can // execute code) and uses the scope properties, but doesn't // require this code to use the unstable OBJ_IS_NATIVE API. JSObject *etor = JS_NewPropertyIterator(cx, p); if (!etor) return NS_ERROR_OUT_OF_MEMORY; jsid id; while (JS_NextProperty(cx, etor, &id) && !JSID_IS_VOID(id)) { nsresult rv = AppendProperty(id, cx, aObjectsInReport); NS_ENSURE_SUCCESS(rv, rv); } } if (JS_ObjectIsFunction(cx, obj)) { JSFunction *fun = JS_ValueToFunction(cx, mJSValue); NS_ENSURE_TRUE(fun, NS_ERROR_UNEXPECTED); JSScript *script = JS_GetFunctionScript(cx, fun); if (script) { // null for native code const char *fname = JS_GetScriptFilename(cx, script); // XXX Do we know the encoding of this file name? mFileName = NS_ConvertUTF8toUTF16(fname); mLineStart = JS_GetScriptBaseLineNumber(cx, script); mLineEnd = mLineStart + JS_GetScriptLineExtent(cx, script) - 1; } } } ValueToString(cx, mJSValue, mString); return NS_OK; }