Testcase for bug 542263 - crash at NPObjWrapper_NewResolve or various other places

--HG--
extra : rebase_source : 92a3bc42926934ec4f077657d4c519809fa71df0
This commit is contained in:
Benjamin Smedberg 2010-02-03 09:09:16 -05:00
Родитель 2bbb1c5271
Коммит ba72a63e70
2 изменённых файлов: 161 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,59 @@
<head>
<title>GC race with actors on the parent</title>
<script type="text/javascript"
src="/MochiKit/packed.js"></script>
<script type="text/javascript"
src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css"
href="/tests/SimpleTest/test.css" />
<body onload="setTimeout(checkGCRace, 1000)">
<p id="display"></p>
<embed id="p" type="application/x-test" wmode="window"></embed>
<script class="testbody" type="application/javascript">
SimpleTest.waitForExplicitFinish();
var nested = false;
function cb(f) {
ok(!nested, "Callback shouldn't occur in a nested stack frame");
try {
f(35);
ok(true, "Callback was called, no crash");
}
catch (e) {
ok(false, "Exception calling callback object: " + e);
}
SimpleTest.executeSoon(removePlugin);
}
function removePlugin() {
var p = document.getElementById('p');
p.parentNode.removeChild(p);
p = null;
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
Components.utils.forceGC();
SimpleTest.finish();
}
function checkGCRace() {
nested = true;
// The plugin will hand back a function and immediately sleep.
// We will lose our only reference to the function and force GC, followed
// by calling us with that function object again. We should be able to
// call the function and not crash.
var p = document.getElementById('p');
var f = p.checkGCRace(cb);
f = null; // 'f' should be collected next GC
nested = false;
setTimeout(function() {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
Components.utils.forceGC();
}, 2000);
}
</script>

Просмотреть файл

@ -46,6 +46,7 @@
#ifdef XP_WIN
#include <process.h>
#include <float.h>
#include <windows.h>
#define getpid _getpid
#else
#include <unistd.h>
@ -144,6 +145,7 @@ static bool setCookie(NPObject* npobj, const NPVariant* args, uint32_t argCount,
static bool getCookie(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool getAuthInfo(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool asyncCallbackTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool checkGCRace(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static const NPUTF8* sPluginMethodIdentifierNames[] = {
"npnEvaluateTest",
@ -181,6 +183,7 @@ static const NPUTF8* sPluginMethodIdentifierNames[] = {
"getCookie",
"getAuthInfo",
"asyncCallbackTest",
"checkGCRace",
};
static NPIdentifier sPluginMethodIdentifiers[ARRAY_LENGTH(sPluginMethodIdentifierNames)];
static const ScriptableFunction sPluginMethodFunctions[ARRAY_LENGTH(sPluginMethodIdentifierNames)] = {
@ -219,6 +222,7 @@ static const ScriptableFunction sPluginMethodFunctions[ARRAY_LENGTH(sPluginMetho
getCookie,
getAuthInfo,
asyncCallbackTest,
checkGCRace,
};
struct URLNotifyData
@ -2450,3 +2454,101 @@ asyncCallbackTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPV
return true;
}
static bool
GCRaceInvoke(NPObject*, NPIdentifier, const NPVariant*, uint32_t, NPVariant*)
{
return false;
}
static bool
GCRaceInvokeDefault(NPObject* o, const NPVariant* args, uint32_t argCount,
NPVariant* result)
{
if (1 != argCount || !NPVARIANT_IS_INT32(args[0]) ||
35 != NPVARIANT_TO_INT32(args[0]))
return false;
return true;
}
static const NPClass kGCRaceClass = {
NP_CLASS_STRUCT_VERSION,
NULL,
NULL,
NULL,
NULL,
GCRaceInvoke,
GCRaceInvokeDefault,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
struct GCRaceData
{
GCRaceData(NPP npp, NPObject* callback, NPObject* localFunc)
: npp_(npp)
, callback_(callback)
, localFunc_(localFunc)
{
NPN_RetainObject(callback_);
NPN_RetainObject(localFunc_);
}
~GCRaceData()
{
NPN_ReleaseObject(callback_);
NPN_ReleaseObject(localFunc_);
}
NPP npp_;
NPObject* callback_;
NPObject* localFunc_;
};
static void
FinishGCRace(void* closure)
{
GCRaceData* rd = static_cast<GCRaceData*>(closure);
#ifdef XP_WIN
Sleep(5000);
#else
sleep(5);
#endif
NPVariant arg;
OBJECT_TO_NPVARIANT(rd->localFunc_, arg);
NPVariant result;
bool ok = NPN_InvokeDefault(rd->npp_, rd->callback_, &arg, 1, &result);
if (!ok)
return;
NPN_ReleaseVariantValue(&result);
delete rd;
}
bool
checkGCRace(NPObject* npobj, const NPVariant* args, uint32_t argCount,
NPVariant* result)
{
if (1 != argCount || !NPVARIANT_IS_OBJECT(args[0]))
return false;
NPP npp = static_cast<TestNPObject*>(npobj)->npp;
NPObject* localFunc =
NPN_CreateObject(npp, const_cast<NPClass*>(&kGCRaceClass));
GCRaceData* rd =
new GCRaceData(npp, NPVARIANT_TO_OBJECT(args[0]), localFunc);
NPN_PluginThreadAsyncCall(npp, FinishGCRace, rd);
OBJECT_TO_NPVARIANT(localFunc, *result);
return true;
}