blob: fc7bc76c8a2180dfe34d59eceb2650109c4a3a9b [file] [log] [blame]
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
*/
/* 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 : JS::Traceable
{
explicit MyHeap(JSObject* obj) : weak(obj) {}
js::WeakRef<JSObject*> weak;
static void trace(MyHeap* self, JSTracer* trc) {
js::TraceWeakEdge(trc, &self->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;
rt->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(rt);
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(rt);
CHECK(heap.get().weak == nullptr);
return true;
}
END_TEST(testGCWeakRef)