1// Copyright 2020 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include 'src/builtins/builtins-collections-gen.h'
6
7namespace runtime {
8
9extern runtime JSWeakRefAddToKeptObjects(implicit context: Context)(
10    JSReceiver | Symbol): void;
11
12}  // namespace runtime
13
14namespace weakref {
15
16// https://tc39.es/ecma262/#sec-weak-ref-target
17transitioning javascript builtin
18WeakRefConstructor(
19    js-implicit context: NativeContext, receiver: JSAny, newTarget: JSAny,
20    target: JSFunction)(weakTarget: JSAny): JSWeakRef {
21  // 1. If NewTarget is undefined, throw a TypeError exception.
22  if (newTarget == Undefined) {
23    ThrowTypeError(MessageTemplate::kConstructorNotFunction, 'WeakRef');
24  }
25
26  // 2. If CanBeHeldWeakly(weakTarget) is false, throw a TypeError exception.
27  GotoIfCannotBeHeldWeakly(weakTarget) otherwise ThrowTypeError(
28      MessageTemplate::kInvalidWeakRefsWeakRefConstructorTarget);
29
30  // 3. Let weakRef be ? OrdinaryCreateFromConstructor(NewTarget,
31  // "%WeakRefPrototype%", « [[WeakRefTarget]] »).
32  const map = GetDerivedMap(target, UnsafeCast<JSReceiver>(newTarget));
33  const weakRef = UnsafeCast<JSWeakRef>(AllocateFastOrSlowJSObjectFromMap(map));
34  // 4. Perfom ! AddToKeptObjects(target).
35  const weakTarget = UnsafeCast<(JSReceiver | Symbol)>(weakTarget);
36  runtime::JSWeakRefAddToKeptObjects(weakTarget);
37  // 5. Set weakRef.[[WeakRefTarget]] to target.
38  weakRef.target = weakTarget;
39  // 6. Return weakRef.
40  return weakRef;
41}
42
43transitioning javascript builtin
44WeakRefDeref(js-implicit context: NativeContext, receiver: JSAny)(): JSAny {
45  // 1. Let weakRef be the this value.
46  // 2. Perform ? RequireInternalSlot(weakRef, [[WeakRefTarget]]).
47  const weakRef = Cast<JSWeakRef>(receiver) otherwise
48  ThrowTypeError(
49      MessageTemplate::kIncompatibleMethodReceiver, 'WeakRef.prototype.deref',
50      receiver);
51  // 3. Let target be the value of weakRef.[[WeakRefTarget]].
52  const target = weakRef.target;
53  // 4. If target is not empty,
54  //   a. Perform ! AddToKeptObjects(target).
55  //   b. Return target.
56  // 5. Return undefined.
57  if (target != Undefined) {
58    // JSWeakRefAddToKeptObjects might allocate and cause a GC, but it
59    // won't clear `target` since we hold it here on the stack.
60    runtime::JSWeakRefAddToKeptObjects(
61        UnsafeCast<(JSReceiver | Symbol)>(target));
62  }
63  return target;
64}
65
66}  // namespace weakrefs
67