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
5namespace runtime {
6
7extern runtime JSWeakRefAddToKeptObjects(implicit context: Context)(JSReceiver);
8
9}  // namespace runtime
10
11namespace weakref {
12
13transitioning javascript builtin
14WeakRefConstructor(
15    js-implicit context: NativeContext, receiver: JSAny, newTarget: JSAny,
16    target: JSFunction)(weakTarget: JSAny): JSWeakRef {
17  // 1. If NewTarget is undefined, throw a TypeError exception.
18  if (newTarget == Undefined) {
19    ThrowTypeError(MessageTemplate::kConstructorNotFunction, 'WeakRef');
20  }
21  // 2. If Type(target) is not Object, throw a TypeError exception.
22  const weakTarget = Cast<JSReceiver>(weakTarget) otherwise
23  ThrowTypeError(
24      MessageTemplate::kWeakRefsWeakRefConstructorTargetMustBeObject);
25  // 3. Let weakRef be ? OrdinaryCreateFromConstructor(NewTarget,
26  // "%WeakRefPrototype%", « [[WeakRefTarget]] »).
27  const map = GetDerivedMap(target, UnsafeCast<JSReceiver>(newTarget));
28  const weakRef = UnsafeCast<JSWeakRef>(AllocateFastOrSlowJSObjectFromMap(map));
29  // 4. Perfom ! AddToKeptObjects(target).
30  runtime::JSWeakRefAddToKeptObjects(weakTarget);
31  // 5. Set weakRef.[[WeakRefTarget]] to target.
32  weakRef.target = weakTarget;
33  // 6. Return weakRef.
34  return weakRef;
35}
36
37transitioning javascript builtin
38WeakRefDeref(js-implicit context: NativeContext, receiver: JSAny)(): JSAny {
39  // 1. Let weakRef be the this value.
40  // 2. Perform ? RequireInternalSlot(weakRef, [[WeakRefTarget]]).
41  const weakRef = Cast<JSWeakRef>(receiver) otherwise
42  ThrowTypeError(
43      MessageTemplate::kIncompatibleMethodReceiver, 'WeakRef.prototype.deref',
44      receiver);
45  // 3. Let target be the value of weakRef.[[WeakRefTarget]].
46  const target = weakRef.target;
47  // 4. If target is not empty,
48  //   a. Perform ! AddToKeptObjects(target).
49  //   b. Return target.
50  // 5. Return undefined.
51  if (target != Undefined) {
52    // JSWeakRefAddToKeptObjects might allocate and cause a GC, but it
53    // won't clear `target` since we hold it here on the stack.
54    runtime::JSWeakRefAddToKeptObjects(UnsafeCast<JSReceiver>(target));
55  }
56  return target;
57}
58
59}  // namespace weakrefs
60