/src/hermes/lib/VM/JSLib/WeakSet.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) Meta Platforms, Inc. and affiliates. |
3 | | * |
4 | | * This source code is licensed under the MIT license found in the |
5 | | * LICENSE file in the root directory of this source tree. |
6 | | */ |
7 | | |
8 | | #include "JSLibInternal.h" |
9 | | |
10 | | #include "hermes/VM/CellKind.h" |
11 | | #include "hermes/VM/JSWeakMapImpl.h" |
12 | | #include "hermes/VM/StringPrimitive.h" |
13 | | |
14 | | namespace hermes { |
15 | | namespace vm { |
16 | | |
17 | 113 | Handle<JSObject> createWeakSetConstructor(Runtime &runtime) { |
18 | 113 | auto weakSetPrototype = Handle<JSObject>::vmcast(&runtime.weakSetPrototype); |
19 | | |
20 | 113 | defineMethod( |
21 | 113 | runtime, |
22 | 113 | weakSetPrototype, |
23 | 113 | Predefined::getSymbolID(Predefined::add), |
24 | 113 | nullptr, |
25 | 113 | weakSetPrototypeAdd, |
26 | 113 | 1); |
27 | | |
28 | 113 | defineMethod( |
29 | 113 | runtime, |
30 | 113 | weakSetPrototype, |
31 | 113 | Predefined::getSymbolID(Predefined::deleteStr), |
32 | 113 | nullptr, |
33 | 113 | weakSetPrototypeDelete, |
34 | 113 | 1); |
35 | | |
36 | 113 | defineMethod( |
37 | 113 | runtime, |
38 | 113 | weakSetPrototype, |
39 | 113 | Predefined::getSymbolID(Predefined::has), |
40 | 113 | nullptr, |
41 | 113 | weakSetPrototypeHas, |
42 | 113 | 1); |
43 | | |
44 | 113 | DefinePropertyFlags dpf = DefinePropertyFlags::getDefaultNewPropertyFlags(); |
45 | 113 | dpf.writable = 0; |
46 | 113 | dpf.enumerable = 0; |
47 | 113 | defineProperty( |
48 | 113 | runtime, |
49 | 113 | weakSetPrototype, |
50 | 113 | Predefined::getSymbolID(Predefined::SymbolToStringTag), |
51 | 113 | runtime.getPredefinedStringHandle(Predefined::WeakSet), |
52 | 113 | dpf); |
53 | | |
54 | 113 | auto cons = defineSystemConstructor<JSWeakSet>( |
55 | 113 | runtime, |
56 | 113 | Predefined::getSymbolID(Predefined::WeakSet), |
57 | 113 | weakSetConstructor, |
58 | 113 | weakSetPrototype, |
59 | 113 | 0, |
60 | 113 | CellKind::JSWeakSetKind); |
61 | | |
62 | | // ES6.0 23.4.3.1 |
63 | 113 | defineProperty( |
64 | 113 | runtime, |
65 | 113 | weakSetPrototype, |
66 | 113 | Predefined::getSymbolID(Predefined::constructor), |
67 | 113 | cons); |
68 | | |
69 | 113 | return cons; |
70 | 113 | } |
71 | | |
72 | | CallResult<HermesValue> |
73 | 0 | weakSetConstructor(void *, Runtime &runtime, NativeArgs args) { |
74 | 0 | GCScope gcScope{runtime}; |
75 | |
|
76 | 0 | if (LLVM_UNLIKELY(!args.isConstructorCall())) { |
77 | 0 | return runtime.raiseTypeError("WeakSet must be called as a constructor"); |
78 | 0 | } |
79 | | |
80 | 0 | auto selfHandle = args.dyncastThis<JSWeakSet>(); |
81 | |
|
82 | 0 | if (args.getArgCount() == 0 || args.getArg(0).isUndefined() || |
83 | 0 | args.getArg(0).isNull()) { |
84 | 0 | return selfHandle.getHermesValue(); |
85 | 0 | } |
86 | | |
87 | 0 | auto propRes = JSObject::getNamed_RJS( |
88 | 0 | selfHandle, runtime, Predefined::getSymbolID(Predefined::add)); |
89 | 0 | if (LLVM_UNLIKELY(propRes == ExecutionStatus::EXCEPTION)) { |
90 | 0 | return ExecutionStatus::EXCEPTION; |
91 | 0 | } |
92 | 0 | auto adder = |
93 | 0 | Handle<Callable>::dyn_vmcast(runtime.makeHandle(std::move(*propRes))); |
94 | 0 | if (LLVM_UNLIKELY(!adder)) { |
95 | 0 | return runtime.raiseTypeError("Property 'add' for WeakSet is not callable"); |
96 | 0 | } |
97 | | |
98 | 0 | auto iterRes = getIterator(runtime, args.getArgHandle(0)); |
99 | 0 | if (LLVM_UNLIKELY(iterRes == ExecutionStatus::EXCEPTION)) { |
100 | 0 | return ExecutionStatus::EXCEPTION; |
101 | 0 | } |
102 | 0 | auto iteratorRecord = *iterRes; |
103 | |
|
104 | 0 | auto marker = gcScope.createMarker(); |
105 | 0 | for (;;) { |
106 | 0 | gcScope.flushToMarker(marker); |
107 | 0 | CallResult<Handle<JSObject>> nextRes = |
108 | 0 | iteratorStep(runtime, iteratorRecord); |
109 | 0 | if (LLVM_UNLIKELY(nextRes == ExecutionStatus::EXCEPTION)) { |
110 | 0 | return ExecutionStatus::EXCEPTION; |
111 | 0 | } |
112 | 0 | if (!*nextRes) { |
113 | | // Done with iteration. |
114 | 0 | return selfHandle.getHermesValue(); |
115 | 0 | } |
116 | 0 | auto nextValueRes = JSObject::getNamed_RJS( |
117 | 0 | *nextRes, runtime, Predefined::getSymbolID(Predefined::value)); |
118 | 0 | if (LLVM_UNLIKELY(nextValueRes == ExecutionStatus::EXCEPTION)) { |
119 | 0 | return ExecutionStatus::EXCEPTION; |
120 | 0 | } |
121 | | |
122 | 0 | if (LLVM_UNLIKELY( |
123 | 0 | Callable::executeCall1( |
124 | 0 | adder, runtime, selfHandle, nextValueRes->get()) == |
125 | 0 | ExecutionStatus::EXCEPTION)) { |
126 | 0 | return iteratorCloseAndRethrow(runtime, iteratorRecord.iterator); |
127 | 0 | } |
128 | 0 | } |
129 | | |
130 | 0 | return HermesValue::encodeUndefinedValue(); |
131 | 0 | } |
132 | | |
133 | | CallResult<HermesValue> |
134 | 0 | weakSetPrototypeAdd(void *, Runtime &runtime, NativeArgs args) { |
135 | 0 | auto M = args.dyncastThis<JSWeakSet>(); |
136 | 0 | if (LLVM_UNLIKELY(!M)) { |
137 | 0 | return runtime.raiseTypeError( |
138 | 0 | "WeakSet.prototype.add can only be called on a WeakSet"); |
139 | 0 | } |
140 | | |
141 | 0 | auto key = args.dyncastArg<JSObject>(0); |
142 | 0 | if (LLVM_UNLIKELY(!key)) { |
143 | 0 | return runtime.raiseTypeError("WeakSet key must be an Object"); |
144 | 0 | } |
145 | | |
146 | 0 | if (LLVM_UNLIKELY( |
147 | 0 | JSWeakSet::setValue( |
148 | 0 | M, runtime, key, HandleRootOwner::getUndefinedValue()) == |
149 | 0 | ExecutionStatus::EXCEPTION)) { |
150 | 0 | return ExecutionStatus::EXCEPTION; |
151 | 0 | } |
152 | | |
153 | 0 | return M.getHermesValue(); |
154 | 0 | } |
155 | | |
156 | | CallResult<HermesValue> |
157 | 0 | weakSetPrototypeDelete(void *, Runtime &runtime, NativeArgs args) { |
158 | 0 | auto M = args.dyncastThis<JSWeakSet>(); |
159 | 0 | if (LLVM_UNLIKELY(!M)) { |
160 | 0 | return runtime.raiseTypeError( |
161 | 0 | "WeakSet.prototype.delete can only be called on a WeakSet"); |
162 | 0 | } |
163 | | |
164 | 0 | auto key = args.dyncastArg<JSObject>(0); |
165 | 0 | if (LLVM_UNLIKELY(!key)) { |
166 | 0 | return HermesValue::encodeBoolValue(false); |
167 | 0 | } |
168 | | |
169 | 0 | return HermesValue::encodeBoolValue(JSWeakSet::deleteValue(M, runtime, key)); |
170 | 0 | } |
171 | | |
172 | | CallResult<HermesValue> |
173 | 0 | weakSetPrototypeHas(void *, Runtime &runtime, NativeArgs args) { |
174 | 0 | auto M = args.dyncastThis<JSWeakSet>(); |
175 | 0 | if (LLVM_UNLIKELY(!M)) { |
176 | 0 | return runtime.raiseTypeError( |
177 | 0 | "WeakSet.prototype.has can only be called on a WeakSet"); |
178 | 0 | } |
179 | | |
180 | 0 | auto key = args.dyncastArg<JSObject>(0); |
181 | 0 | if (LLVM_UNLIKELY(!key)) { |
182 | 0 | return HermesValue::encodeBoolValue(false); |
183 | 0 | } |
184 | | |
185 | 0 | return HermesValue::encodeBoolValue(JSWeakSet::hasValue(M, runtime, key)); |
186 | 0 | } |
187 | | |
188 | | } // namespace vm |
189 | | } // namespace hermes |