Coverage Report

Created: 2025-12-12 07:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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