WeakMapObject-inl.h (3182B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef builtin_WeakMapObject_inl_h 8 #define builtin_WeakMapObject_inl_h 9 10 #include "builtin/WeakMapObject.h" 11 12 #include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_* 13 #include "js/Prefs.h" 14 #include "js/Wrapper.h" 15 #include "gc/WeakMap-inl.h" 16 #include "vm/JSObject-inl.h" 17 18 namespace js { 19 20 static bool TryPreserveReflector(JSContext* cx, HandleObject obj) { 21 if (!MaybePreserveDOMWrapper(cx, obj)) { 22 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, 23 JSMSG_BAD_WEAKMAP_KEY); 24 return false; 25 } 26 27 return true; 28 } 29 30 static MOZ_ALWAYS_INLINE bool EnsureObjectHasWeakMap( 31 JSContext* cx, WeakCollectionObject* obj) { 32 if (obj->getMap()) { 33 return true; 34 } 35 auto newMap = cx->make_unique<WeakCollectionObject::Map>(cx, obj); 36 if (!newMap) { 37 return false; 38 } 39 WeakCollectionObject::Map* map = newMap.release(); 40 InitReservedSlot(obj, WeakCollectionObject::DataSlot, map, 41 MemoryUse::WeakMapObject); 42 return true; 43 } 44 45 static MOZ_ALWAYS_INLINE bool PreserveReflectorAndAssertValidEntry( 46 JSContext* cx, Handle<WeakCollectionObject*> obj, HandleValue key, 47 HandleValue value) { 48 if (key.isObject()) { 49 RootedObject keyObj(cx, &key.toObject()); 50 51 // Preserve wrapped native keys to prevent wrapper optimization. 52 if (!TryPreserveReflector(cx, keyObj)) { 53 return false; 54 } 55 56 RootedObject delegate(cx, UncheckedUnwrapWithoutExpose(keyObj)); 57 if (delegate && !TryPreserveReflector(cx, delegate)) { 58 return false; 59 } 60 } 61 62 MOZ_ASSERT_IF(key.isObject(), 63 key.toObject().compartment() == obj->compartment()); 64 MOZ_ASSERT_IF(value.isGCThing(), 65 gc::ToMarkable(value)->zoneFromAnyThread() == obj->zone() || 66 gc::ToMarkable(value)->zoneFromAnyThread()->isAtomsZone()); 67 MOZ_ASSERT_IF(value.isObject(), 68 value.toObject().compartment() == obj->compartment()); 69 return true; 70 } 71 72 static MOZ_ALWAYS_INLINE bool WeakCollectionPutEntryInternal( 73 JSContext* cx, Handle<WeakCollectionObject*> obj, HandleValue key, 74 HandleValue value) { 75 if (!EnsureObjectHasWeakMap(cx, obj)) { 76 return false; 77 } 78 79 if (!PreserveReflectorAndAssertValidEntry(cx, obj, key, value)) { 80 return false; 81 } 82 83 if (!obj->getMap()->put(key, value)) { 84 JS_ReportOutOfMemory(cx); 85 return false; 86 } 87 return true; 88 } 89 90 static unsigned GetErrorNumber(bool isWeakMap) { 91 bool symbolsAsWeakMapKeysEnabled = 92 JS::Prefs::experimental_symbols_as_weakmap_keys(); 93 94 if (symbolsAsWeakMapKeysEnabled) { 95 return isWeakMap ? JSMSG_WEAKMAP_KEY_CANT_BE_HELD_WEAKLY 96 : JSMSG_WEAKSET_VAL_CANT_BE_HELD_WEAKLY; 97 } 98 99 return isWeakMap ? JSMSG_WEAKMAP_KEY_MUST_BE_AN_OBJECT 100 : JSMSG_WEAKSET_VAL_MUST_BE_AN_OBJECT; 101 } 102 103 } // namespace js 104 105 #endif /* builtin_WeakMapObject_inl_h */