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