michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "js/WeakMapPtr.h" michael@0: michael@0: #include "jsweakmap.h" michael@0: michael@0: // michael@0: // Machinery for the externally-linkable JS::WeakMapPtr, which wraps js::WeakMap michael@0: // for a few public data types. michael@0: // michael@0: michael@0: using namespace js; michael@0: michael@0: namespace { michael@0: michael@0: template michael@0: struct DataType michael@0: { michael@0: }; michael@0: michael@0: template<> michael@0: struct DataType michael@0: { michael@0: typedef EncapsulatedPtrObject Encapsulated; michael@0: static JSObject *NullValue() { return nullptr; } michael@0: }; michael@0: michael@0: template<> michael@0: struct DataType michael@0: { michael@0: typedef EncapsulatedValue Encapsulated; michael@0: static JS::Value NullValue() { return JS::UndefinedValue(); } michael@0: }; michael@0: michael@0: template michael@0: struct Utils michael@0: { michael@0: typedef typename DataType::Encapsulated KeyType; michael@0: typedef typename DataType::Encapsulated ValueType; michael@0: typedef WeakMap Type; michael@0: typedef Type* PtrType; michael@0: static PtrType cast(void *ptr) { return static_cast(ptr); } michael@0: }; michael@0: michael@0: } /* namespace */ michael@0: michael@0: template michael@0: void michael@0: JS::WeakMapPtr::destroy() michael@0: { michael@0: MOZ_ASSERT(initialized()); michael@0: auto map = Utils::cast(ptr); michael@0: // If this destruction happens mid-GC, we might be in the compartment's list michael@0: // of known live weakmaps. If we are, remove ourselves before deleting. michael@0: if (map->isInList()) michael@0: WeakMapBase::removeWeakMapFromList(map); michael@0: map->check(); michael@0: js_delete(map); michael@0: ptr = nullptr; michael@0: } michael@0: michael@0: template michael@0: bool michael@0: JS::WeakMapPtr::init(JSContext *cx) michael@0: { michael@0: MOZ_ASSERT(!initialized()); michael@0: typename Utils::PtrType map = cx->runtime()->new_::Type>(cx); michael@0: if (!map || !map->init()) michael@0: return false; michael@0: ptr = map; michael@0: return true; michael@0: } michael@0: michael@0: template michael@0: void michael@0: JS::WeakMapPtr::trace(JSTracer *trc) michael@0: { michael@0: MOZ_ASSERT(initialized()); michael@0: return Utils::cast(ptr)->trace(trc); michael@0: } michael@0: michael@0: template michael@0: V michael@0: JS::WeakMapPtr::lookup(const K &key) michael@0: { michael@0: MOZ_ASSERT(initialized()); michael@0: typename Utils::Type::Ptr result = Utils::cast(ptr)->lookup(key); michael@0: if (!result) michael@0: return DataType::NullValue(); michael@0: return result->value(); michael@0: } michael@0: michael@0: template michael@0: /* static */ void michael@0: JS::WeakMapPtr::keyMarkCallback(JSTracer *trc, K key, void *data) michael@0: { michael@0: auto map = static_cast< JS::WeakMapPtr* >(data); michael@0: K prior = key; michael@0: JS_CallObjectTracer(trc, &key, "WeakMapPtr key"); michael@0: return Utils::cast(map->ptr)->rekeyIfMoved(prior, key); michael@0: } michael@0: michael@0: template michael@0: bool michael@0: JS::WeakMapPtr::put(JSContext *cx, const K &key, const V &value) michael@0: { michael@0: MOZ_ASSERT(initialized()); michael@0: if (!Utils::cast(ptr)->put(key, value)) michael@0: return false; michael@0: JS_StoreObjectPostBarrierCallback(cx, keyMarkCallback, key, this); michael@0: // Values do not need to be barriered because only put() is supported, michael@0: // which is always an initializing write. michael@0: return true; michael@0: } michael@0: michael@0: // michael@0: // Supported specializations of JS::WeakMap: michael@0: // michael@0: michael@0: template class JS::WeakMapPtr; michael@0: michael@0: #ifdef DEBUG michael@0: // Nobody's using this at the moment, but we want to make sure it compiles. michael@0: template class JS::WeakMapPtr; michael@0: #endif