/ runtime / SetPrototype.cpp
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  }