WeakMapPrototype.cpp
1 /* 2 * Copyright (C) 2013-2019 Apple, Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "WeakMapPrototype.h" 28 29 #include "JSCInlines.h" 30 #include "JSWeakMap.h" 31 32 namespace JSC { 33 34 const ClassInfo WeakMapPrototype::s_info = { "WeakMap", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(WeakMapPrototype) }; 35 36 static JSC_DECLARE_HOST_FUNCTION(protoFuncWeakMapDelete); 37 static JSC_DECLARE_HOST_FUNCTION(protoFuncWeakMapGet); 38 static JSC_DECLARE_HOST_FUNCTION(protoFuncWeakMapHas); 39 static JSC_DECLARE_HOST_FUNCTION(protoFuncWeakMapSet); 40 41 void WeakMapPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject) 42 { 43 Base::finishCreation(vm); 44 ASSERT(inherits(vm, info())); 45 46 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->deleteKeyword, protoFuncWeakMapDelete, static_cast<unsigned>(PropertyAttribute::DontEnum), 1); 47 JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->get, protoFuncWeakMapGet, static_cast<unsigned>(PropertyAttribute::DontEnum), 1, JSWeakMapGetIntrinsic); 48 JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->has, protoFuncWeakMapHas, static_cast<unsigned>(PropertyAttribute::DontEnum), 1, JSWeakMapHasIntrinsic); 49 JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->set, protoFuncWeakMapSet, static_cast<unsigned>(PropertyAttribute::DontEnum), 2, JSWeakMapSetIntrinsic); 50 51 JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); 52 } 53 54 ALWAYS_INLINE static JSWeakMap* getWeakMap(JSGlobalObject* globalObject, JSValue value) 55 { 56 VM& vm = globalObject->vm(); 57 auto scope = DECLARE_THROW_SCOPE(vm); 58 59 if (UNLIKELY(!value.isObject())) { 60 throwTypeError(globalObject, scope, "Called WeakMap function on non-object"_s); 61 return nullptr; 62 } 63 64 auto* map = jsDynamicCast<JSWeakMap*>(vm, asObject(value)); 65 if (LIKELY(map)) 66 return map; 67 68 throwTypeError(globalObject, scope, "Called WeakMap function on a non-WeakMap object"_s); 69 return nullptr; 70 } 71 72 JSC_DEFINE_HOST_FUNCTION(protoFuncWeakMapDelete, (JSGlobalObject* globalObject, CallFrame* callFrame)) 73 { 74 auto* map = getWeakMap(globalObject, callFrame->thisValue()); 75 if (!map) 76 return JSValue::encode(jsUndefined()); 77 JSValue key = callFrame->argument(0); 78 return JSValue::encode(jsBoolean(key.isObject() && map->remove(asObject(key)))); 79 } 80 81 JSC_DEFINE_HOST_FUNCTION(protoFuncWeakMapGet, (JSGlobalObject* globalObject, CallFrame* callFrame)) 82 { 83 auto* map = getWeakMap(globalObject, callFrame->thisValue()); 84 if (!map) 85 return JSValue::encode(jsUndefined()); 86 JSValue key = callFrame->argument(0); 87 if (!key.isObject()) 88 return JSValue::encode(jsUndefined()); 89 return JSValue::encode(map->get(asObject(key))); 90 } 91 92 JSC_DEFINE_HOST_FUNCTION(protoFuncWeakMapHas, (JSGlobalObject* globalObject, CallFrame* callFrame)) 93 { 94 auto* map = getWeakMap(globalObject, callFrame->thisValue()); 95 if (!map) 96 return JSValue::encode(jsUndefined()); 97 JSValue key = callFrame->argument(0); 98 return JSValue::encode(jsBoolean(key.isObject() && map->has(asObject(key)))); 99 } 100 101 JSC_DEFINE_HOST_FUNCTION(protoFuncWeakMapSet, (JSGlobalObject* globalObject, CallFrame* callFrame)) 102 { 103 VM& vm = globalObject->vm(); 104 auto scope = DECLARE_THROW_SCOPE(vm); 105 106 auto* map = getWeakMap(globalObject, callFrame->thisValue()); 107 EXCEPTION_ASSERT(!!scope.exception() == !map); 108 if (!map) 109 return JSValue::encode(jsUndefined()); 110 JSValue key = callFrame->argument(0); 111 if (!key.isObject()) 112 return JSValue::encode(throwTypeError(globalObject, scope, "Attempted to set a non-object key in a WeakMap"_s)); 113 map->set(vm, asObject(key), callFrame->argument(1)); 114 return JSValue::encode(callFrame->thisValue()); 115 } 116 117 }