DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (b66b287a2650)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
#include "tests.h"
#include "jsstr.h"

static JSGCCallback oldGCCallback;

static void **checkPointers;
static jsuint checkPointersLength;

static JSBool
TestAboutToBeFinalizedCallback(JSContext *cx, JSGCStatus status)
{
    if (status == JSGC_MARK_END && checkPointers) {
        for (jsuint i = 0; i != checkPointersLength; ++i) {
            void *p = checkPointers[i];
            JS_ASSERT(p);
            if (JS_IsAboutToBeFinalized(cx, p))
                checkPointers[i] = NULL;
        }
    }

    return !oldGCCallback || oldGCCallback(cx, status);
}

BEGIN_TEST(testIsAboutToBeFinalized_bug528645)
{
    jsvalRoot root(cx);

    /*
     * Check various types of GC things against JS_IsAboutToBeFinalized.
     * Make sure to include unit and numeric strings to the set.
     */
    EVAL("var x = 1.1; "
         "[x + 0.1, ''+x, 'a', '42', 'something'.substring(1), "
         "{}, [], new Function('return 10;'), <xml/>];",
         root.addr());

    JSObject *array = JSVAL_TO_OBJECT(root.value());
    JS_ASSERT(JS_IsArrayObject(cx, array));

    JSBool ok = JS_GetArrayLength(cx, array, &checkPointersLength);
    CHECK(ok);

    void **elems = (void **) malloc(sizeof(void *) * checkPointersLength);
    CHECK(elems);

    size_t staticStrings = 0;
    for (jsuint i = 0; i != checkPointersLength; ++i) {
        jsval v;
        ok = JS_GetElement(cx, array, i, &v);
        CHECK(ok);
        JS_ASSERT(JSVAL_IS_GCTHING(v));
        JS_ASSERT(!JSVAL_IS_NULL(v));
        elems[i] = JSVAL_TO_GCTHING(v);
        if (JSString::isStatic(elems[i]))
            ++staticStrings;
    }

    oldGCCallback = JS_SetGCCallback(cx, TestAboutToBeFinalizedCallback);
    checkPointers = elems;
    JS_GC(cx);

    /*
     * All GC things are rooted via the root holding the array containing them
     * and TestAboutToBeFinalizedCallback must keep them as is.
     */
    for (jsuint i = 0; i != checkPointersLength; ++i)
        CHECK(checkPointers[i]);

    root = JSVAL_NULL;
    JS_GC(cx);

    /* Everything is unrooted except unit strings. */
    for (jsuint i = 0; i != checkPointersLength; ++i) {
        void *p = checkPointers[i];
        if (p) {
            CHECK(JSString::isStatic(p));
            CHECK(staticStrings != 0);
            --staticStrings;
        }
    }
    CHECK(staticStrings == 0);

    checkPointers = NULL;
    JS_SetGCCallback(cx, oldGCCallback);
    free(elems);

    return true;
}
END_TEST(testIsAboutToBeFinalized_bug528645)