summaryrefslogtreecommitdiff
path: root/js/src/jsapi-tests/testGCWeakRef.cpp
blob: 11e6832d967917462e7e83eec05bdde20130cc1e (plain)
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
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "gc/Barrier.h"
#include "js/RootingAPI.h"

#include "jsapi-tests/tests.h"

struct MyHeap
{
    explicit MyHeap(JSObject* obj) : weak(obj) {}
    js::WeakRef<JSObject*> weak;

    void trace(JSTracer* trc) {
        js::TraceWeakEdge(trc, &weak, "weak");
    }
};

BEGIN_TEST(testGCWeakRef)
{
    // Create an object and add a property to it so that we can read the
    // property back later to verify that object internals are not garbage.
    JS::RootedObject obj(cx, JS_NewPlainObject(cx));
    CHECK(obj);
    CHECK(JS_DefineProperty(cx, obj, "x", 42, 0));

    // Store the object behind a weak pointer and remove other references.
    JS::Rooted<MyHeap> heap(cx, MyHeap(obj));
    obj = nullptr;

    cx->gc.minorGC(JS::gcreason::API);

    // The minor collection should have treated the weak ref as a strong ref,
    // so the object should still be live, despite not having any other live
    // references.
    CHECK(heap.get().weak.unbarrieredGet() != nullptr);
    obj = heap.get().weak;
    JS::RootedValue v(cx);
    CHECK(JS_GetProperty(cx, obj, "x", &v));
    CHECK(v.isInt32());
    CHECK(v.toInt32() == 42);

    // A full collection with a second ref should keep the object as well.
    CHECK(obj == heap.get().weak);
    JS_GC(cx);
    CHECK(obj == heap.get().weak);
    v = JS::UndefinedValue();
    CHECK(JS_GetProperty(cx, obj, "x", &v));
    CHECK(v.isInt32());
    CHECK(v.toInt32() == 42);

    // A full collection after nulling the root should collect the object, or
    // at least null out the weak reference before returning to the mutator.
    obj = nullptr;
    JS_GC(cx);
    CHECK(heap.get().weak == nullptr);

    return true;
}
END_TEST(testGCWeakRef)