SetPrototype.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 "SetPrototype.h" 28 29 #include "BuiltinNames.h" 30 #include "JSCInlines.h" 31 #include "JSSet.h" 32 #include "JSSetIterator.h" 33 34 #include "SetPrototype.lut.h" 35 36 namespace JSC { 37 38 const ClassInfo SetPrototype::s_info = { "Set", &Base::s_info, &setPrototypeTable, nullptr, CREATE_METHOD_TABLE(SetPrototype) }; 39 40 /* Source for SetIteratorPrototype.lut.h 41 @begin setPrototypeTable 42 forEach JSBuiltin DontEnum|Function 0 43 @end 44 */ 45 46 static JSC_DECLARE_HOST_FUNCTION(setProtoFuncAdd); 47 static JSC_DECLARE_HOST_FUNCTION(setProtoFuncClear); 48 static JSC_DECLARE_HOST_FUNCTION(setProtoFuncDelete); 49 static JSC_DECLARE_HOST_FUNCTION(setProtoFuncHas); 50 static JSC_DECLARE_HOST_FUNCTION(setProtoFuncValues); 51 static JSC_DECLARE_HOST_FUNCTION(setProtoFuncEntries); 52 53 static JSC_DECLARE_HOST_FUNCTION(setProtoFuncSize); 54 55 void SetPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject) 56 { 57 Base::finishCreation(vm); 58 ASSERT(inherits(vm, info())); 59 60 JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->add, setProtoFuncAdd, static_cast<unsigned>(PropertyAttribute::DontEnum), 1, JSSetAddIntrinsic); 61 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->clear, setProtoFuncClear, static_cast<unsigned>(PropertyAttribute::DontEnum), 0); 62 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->deleteKeyword, setProtoFuncDelete, static_cast<unsigned>(PropertyAttribute::DontEnum), 1); 63 JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->has, setProtoFuncHas, static_cast<unsigned>(PropertyAttribute::DontEnum), 1, JSSetHasIntrinsic); 64 JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().entriesPublicName(), setProtoFuncEntries, static_cast<unsigned>(PropertyAttribute::DontEnum), 0, JSSetEntriesIntrinsic); 65 JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().hasPrivateName(), setProtoFuncHas, static_cast<unsigned>(PropertyAttribute::DontEnum), 1, JSSetHasIntrinsic); 66 JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().addPrivateName(), setProtoFuncAdd, static_cast<unsigned>(PropertyAttribute::DontEnum), 1, JSSetAddIntrinsic); 67 68 JSFunction* values = JSFunction::create(vm, globalObject, 0, vm.propertyNames->builtinNames().valuesPublicName().string(), setProtoFuncValues, JSSetValuesIntrinsic); 69 putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().valuesPublicName(), values, static_cast<unsigned>(PropertyAttribute::DontEnum)); 70 putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().keysPublicName(), values, static_cast<unsigned>(PropertyAttribute::DontEnum)); 71 putDirectWithoutTransition(vm, vm.propertyNames->iteratorSymbol, values, static_cast<unsigned>(PropertyAttribute::DontEnum)); 72 JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); 73 74 JSC_NATIVE_GETTER_WITHOUT_TRANSITION(vm.propertyNames->size, setProtoFuncSize, PropertyAttribute::DontEnum | PropertyAttribute::Accessor); 75 76 globalObject->installSetPrototypeWatchpoint(this); 77 } 78 79 ALWAYS_INLINE static JSSet* getSet(JSGlobalObject* globalObject, JSValue thisValue) 80 { 81 VM& vm = globalObject->vm(); 82 auto scope = DECLARE_THROW_SCOPE(vm); 83 84 if (UNLIKELY(!thisValue.isCell())) { 85 throwVMError(globalObject, scope, createNotAnObjectError(globalObject, thisValue)); 86 return nullptr; 87 } 88 auto* set = jsDynamicCast<JSSet*>(vm, thisValue.asCell()); 89 if (LIKELY(set)) 90 return set; 91 throwTypeError(globalObject, scope, "Set operation called on non-Set object"_s); 92 return nullptr; 93 } 94 95 JSC_DEFINE_HOST_FUNCTION(setProtoFuncAdd, (JSGlobalObject* globalObject, CallFrame* callFrame)) 96 { 97 JSValue thisValue = callFrame->thisValue(); 98 JSSet* set = getSet(globalObject, thisValue); 99 if (!set) 100 return JSValue::encode(jsUndefined()); 101 set->add(globalObject, callFrame->argument(0)); 102 return JSValue::encode(thisValue); 103 } 104 105 JSC_DEFINE_HOST_FUNCTION(setProtoFuncClear, (JSGlobalObject* globalObject, CallFrame* callFrame)) 106 { 107 JSSet* set = getSet(globalObject, callFrame->thisValue()); 108 if (!set) 109 return JSValue::encode(jsUndefined()); 110 set->clear(globalObject); 111 return JSValue::encode(jsUndefined()); 112 } 113 114 JSC_DEFINE_HOST_FUNCTION(setProtoFuncDelete, (JSGlobalObject* globalObject, CallFrame* callFrame)) 115 { 116 JSSet* set = getSet(globalObject, callFrame->thisValue()); 117 if (!set) 118 return JSValue::encode(jsUndefined()); 119 return JSValue::encode(jsBoolean(set->remove(globalObject, callFrame->argument(0)))); 120 } 121 122 JSC_DEFINE_HOST_FUNCTION(setProtoFuncHas, (JSGlobalObject* globalObject, CallFrame* callFrame)) 123 { 124 JSSet* set = getSet(globalObject, callFrame->thisValue()); 125 if (!set) 126 return JSValue::encode(jsUndefined()); 127 return JSValue::encode(jsBoolean(set->has(globalObject, callFrame->argument(0)))); 128 } 129 130 JSC_DEFINE_HOST_FUNCTION(setProtoFuncSize, (JSGlobalObject* globalObject, CallFrame* callFrame)) 131 { 132 JSSet* set = getSet(globalObject, callFrame->thisValue()); 133 if (!set) 134 return JSValue::encode(jsUndefined()); 135 return JSValue::encode(jsNumber(set->size())); 136 } 137 138 inline JSValue createSetIteratorObject(JSGlobalObject* globalObject, CallFrame* callFrame, IterationKind kind) 139 { 140 VM& vm = globalObject->vm(); 141 JSValue thisValue = callFrame->thisValue(); 142 JSSet* set = getSet(globalObject, thisValue); 143 if (!set) 144 return jsUndefined(); 145 return JSSetIterator::create(vm, globalObject->setIteratorStructure(), set, kind); 146 } 147 148 JSC_DEFINE_HOST_FUNCTION(setProtoFuncValues, (JSGlobalObject* globalObject, CallFrame* callFrame)) 149 { 150 return JSValue::encode(createSetIteratorObject(globalObject, callFrame, IterationKind::Values)); 151 } 152 153 JSC_DEFINE_HOST_FUNCTION(setProtoFuncEntries, (JSGlobalObject* globalObject, CallFrame* callFrame)) 154 { 155 return JSValue::encode(createSetIteratorObject(globalObject, callFrame, IterationKind::Entries)); 156 } 157 158 }