V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
builtins-weak-refs.cc
1 // Copyright 2018 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-utils-inl.h"
6 #include "src/counters.h"
7 #include "src/objects/js-weak-refs-inl.h"
8 
9 namespace v8 {
10 namespace internal {
11 
12 BUILTIN(WeakFactoryConstructor) {
13  HandleScope scope(isolate);
14  Handle<JSFunction> target = args.target();
15  if (args.new_target()->IsUndefined(isolate)) { // [[Call]]
16  THROW_NEW_ERROR_RETURN_FAILURE(
17  isolate, NewTypeError(MessageTemplate::kConstructorNotFunction,
18  handle(target->shared()->Name(), isolate)));
19  }
20  // [[Construct]]
21  Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
22  Handle<Object> cleanup = args.atOrUndefined(isolate, 1);
23 
24  if (!cleanup->IsCallable()) {
25  THROW_NEW_ERROR_RETURN_FAILURE(
26  isolate, NewTypeError(MessageTemplate::kWeakRefsCleanupMustBeCallable));
27  }
28 
29  Handle<JSObject> result;
30  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
31  isolate, result,
32  JSObject::New(target, new_target, Handle<AllocationSite>::null()));
33 
34  Handle<JSWeakFactory> weak_factory = Handle<JSWeakFactory>::cast(result);
35  weak_factory->set_native_context(*isolate->native_context());
36  weak_factory->set_cleanup(*cleanup);
37  weak_factory->set_flags(
38  JSWeakFactory::ScheduledForCleanupField::encode(false));
39  return *weak_factory;
40 }
41 
42 BUILTIN(WeakFactoryMakeCell) {
43  HandleScope scope(isolate);
44  const char* method_name = "WeakFactory.prototype.makeCell";
45 
46  CHECK_RECEIVER(JSWeakFactory, weak_factory, method_name);
47 
48  Handle<Object> target = args.atOrUndefined(isolate, 1);
49  if (!target->IsJSReceiver()) {
50  THROW_NEW_ERROR_RETURN_FAILURE(
51  isolate,
52  NewTypeError(MessageTemplate::kWeakRefsMakeCellTargetMustBeObject));
53  }
54  Handle<JSReceiver> target_receiver = Handle<JSReceiver>::cast(target);
55  Handle<Object> holdings = args.atOrUndefined(isolate, 2);
56  if (target->SameValue(*holdings)) {
57  THROW_NEW_ERROR_RETURN_FAILURE(
58  isolate,
59  NewTypeError(
60  MessageTemplate::kWeakRefsMakeCellTargetAndHoldingsMustNotBeSame));
61  }
62 
63  // TODO(marja): Realms.
64 
65  Handle<Map> weak_cell_map(isolate->native_context()->js_weak_cell_map(),
66  isolate);
67 
68  // Allocate the JSWeakCell object in the old space, because 1) JSWeakCell
69  // weakness handling is only implemented in the old space 2) they're
70  // supposedly long-living. TODO(marja): Support JSWeakCells in Scavenger.
71  Handle<JSWeakCell> weak_cell =
72  Handle<JSWeakCell>::cast(isolate->factory()->NewJSObjectFromMap(
73  weak_cell_map, TENURED, Handle<AllocationSite>::null()));
74  weak_cell->set_target(*target_receiver);
75  weak_cell->set_holdings(*holdings);
76  weak_factory->AddWeakCell(*weak_cell);
77  return *weak_cell;
78 }
79 
80 BUILTIN(WeakFactoryMakeRef) {
81  HandleScope scope(isolate);
82  const char* method_name = "WeakFactory.prototype.makeRef";
83 
84  CHECK_RECEIVER(JSWeakFactory, weak_factory, method_name);
85 
86  Handle<Object> target = args.atOrUndefined(isolate, 1);
87  if (!target->IsJSReceiver()) {
88  THROW_NEW_ERROR_RETURN_FAILURE(
89  isolate,
90  NewTypeError(MessageTemplate::kWeakRefsMakeRefTargetMustBeObject));
91  }
92  Handle<JSReceiver> target_receiver = Handle<JSReceiver>::cast(target);
93  Handle<Object> holdings = args.atOrUndefined(isolate, 2);
94  if (target->SameValue(*holdings)) {
95  THROW_NEW_ERROR_RETURN_FAILURE(
96  isolate,
97  NewTypeError(
98  MessageTemplate::kWeakRefsMakeRefTargetAndHoldingsMustNotBeSame));
99  }
100 
101  // TODO(marja): Realms.
102 
103  Handle<Map> weak_ref_map(isolate->native_context()->js_weak_ref_map(),
104  isolate);
105 
106  Handle<JSWeakRef> weak_ref =
107  Handle<JSWeakRef>::cast(isolate->factory()->NewJSObjectFromMap(
108  weak_ref_map, TENURED, Handle<AllocationSite>::null()));
109  weak_ref->set_target(*target_receiver);
110  weak_ref->set_holdings(*holdings);
111  weak_factory->AddWeakCell(*weak_ref);
112 
113  isolate->heap()->AddKeepDuringJobTarget(target_receiver);
114 
115  return *weak_ref;
116 }
117 
118 BUILTIN(WeakFactoryCleanupSome) {
119  HandleScope scope(isolate);
120  const char* method_name = "WeakFactory.prototype.cleanupSome";
121 
122  CHECK_RECEIVER(JSWeakFactory, weak_factory, method_name);
123 
124  // Don't do set_scheduled_for_cleanup(false); we still have the microtask
125  // scheduled and don't want to schedule another one in case the user never
126  // executes microtasks.
127  JSWeakFactory::Cleanup(weak_factory, isolate);
128  return ReadOnlyRoots(isolate).undefined_value();
129 }
130 
131 BUILTIN(WeakFactoryCleanupIteratorNext) {
132  HandleScope scope(isolate);
133  CHECK_RECEIVER(JSWeakFactoryCleanupIterator, iterator, "next");
134 
135  Handle<JSWeakFactory> weak_factory(iterator->factory(), isolate);
136  if (!weak_factory->NeedsCleanup()) {
137  return *isolate->factory()->NewJSIteratorResult(
138  handle(ReadOnlyRoots(isolate).undefined_value(), isolate), true);
139  }
140  Handle<JSWeakCell> weak_cell_object =
141  handle(weak_factory->PopClearedCell(isolate), isolate);
142 
143  return *isolate->factory()->NewJSIteratorResult(weak_cell_object, false);
144 }
145 
146 BUILTIN(WeakCellHoldingsGetter) {
147  HandleScope scope(isolate);
148  CHECK_RECEIVER(JSWeakCell, weak_cell, "get WeakCell.holdings");
149  return weak_cell->holdings();
150 }
151 
152 BUILTIN(WeakCellClear) {
153  HandleScope scope(isolate);
154  CHECK_RECEIVER(JSWeakCell, weak_cell, "WeakCell.prototype.clear");
155  weak_cell->Clear(isolate);
156  return ReadOnlyRoots(isolate).undefined_value();
157 }
158 
159 BUILTIN(WeakRefDeref) {
160  HandleScope scope(isolate);
161  CHECK_RECEIVER(JSWeakRef, weak_ref, "WeakRef.prototype.deref");
162  if (weak_ref->target()->IsJSReceiver()) {
163  Handle<JSReceiver> target =
164  handle(JSReceiver::cast(weak_ref->target()), isolate);
165  // AddKeepDuringJobTarget might allocate and cause a GC, but it won't clear
166  // weak_ref since we hold a Handle to its target.
167  isolate->heap()->AddKeepDuringJobTarget(target);
168  } else {
169  DCHECK(weak_ref->target()->IsUndefined(isolate));
170  }
171  return weak_ref->target();
172 }
173 
174 } // namespace internal
175 } // namespace v8
Definition: libplatform.h:13