v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
builtins-disposable-stack.cc
Go to the documentation of this file.
1// Copyright 2024 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
15
16namespace v8 {
17namespace internal {
18
19// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-disposablestack
20BUILTIN(DisposableStackConstructor) {
21 const char* const kMethodName = "DisposableStack";
22 HandleScope scope(isolate);
24
25 // 1. If NewTarget is undefined, throw a TypeError exception.
26 if (IsUndefined(*args.new_target(), isolate)) {
28 isolate, NewTypeError(MessageTemplate::kConstructorNotFunction,
29 isolate->factory()->NewStringFromAsciiChecked(
30 kMethodName)));
31 }
32
33 // 2. Let disposableStack be ? OrdinaryCreateFromConstructor(NewTarget,
34 // "%DisposableStack.prototype%", « [[DisposableState]],
35 // [[DisposeCapability]] »).
37 DirectHandle<JSFunction> target = args.target();
39
41 isolate, map, JSFunction::GetDerivedMap(isolate, target, new_target));
42
44 isolate->factory()->NewJSSyncDisposableStack(map);
45 // 3. Set disposableStack.[[DisposableState]] to pending.
46 // 4. Set disposableStack.[[DisposeCapability]] to NewDisposeCapability().
48 disposable_stack);
49 // 5. Return disposableStack.
50 return *disposable_stack;
51}
52
53// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-disposablestack.prototype.use
54BUILTIN(DisposableStackPrototypeUse) {
55 const char* const kMethodName = "DisposableStack.prototype.use";
56 HandleScope scope(isolate);
57
58 // 1. Let disposableStack be the this value.
59 // 2. Perform ? RequireInternalSlot(disposableStack, [[DisposableState]]).
60 CHECK_RECEIVER(JSSyncDisposableStack, disposable_stack, kMethodName);
61 DirectHandle<JSAny> value = args.at<JSAny>(1);
62
63 // 3. If disposableStack.[[DisposableState]] is disposed, throw a
64 // ReferenceError exception.
65 if (disposable_stack->state() == DisposableStackState::kDisposed) {
67 isolate,
68 NewReferenceError(
69 MessageTemplate::kDisposableStackIsDisposed,
70 isolate->factory()->NewStringFromAsciiChecked(kMethodName)));
71 }
72
73 // 4. Perform ? AddDisposableResource(disposableStack.[[DisposeCapability]],
74 // value, sync-dispose).
75
76 // (a. If V is either null or undefined and hint is sync-dispose, then
77 // i. Return unused.)
78 if (IsNullOrUndefined(*value)) {
79 return *value;
80 }
81
84 isolate, method,
86 isolate, value, DisposeMethodHint::kSyncDispose));
87
88 JSDisposableStackBase::Add(isolate, disposable_stack, value, method,
91
92 // 5. Return value.
93 return *value;
94}
95
96BUILTIN(DisposableStackPrototypeDispose) {
97 const char* const kMethodName = "DisposableStack.prototype.dispose";
98 HandleScope scope(isolate);
99
100 // 1. Let disposableStack be the this value.
101 // 2. Perform ? RequireInternalSlot(disposableStack, [[DisposableState]]).
102 CHECK_RECEIVER(JSSyncDisposableStack, disposable_stack, kMethodName);
103
104 // 3. If disposableStack.[[DisposableState]] is disposed, return undefined.
105 if (disposable_stack->state() == DisposableStackState::kDisposed) {
106 return ReadOnlyRoots(isolate).undefined_value();
107 }
108
109 // 4. Set disposableStack.[[DisposableState]] to disposed.
110 disposable_stack->set_state(DisposableStackState::kDisposed);
111
112 // 5. Return ? DisposeResources(disposableStack.[[DisposeCapability]],
113 // NormalCompletion(undefined)).
116 isolate, result,
118 isolate, disposable_stack, DisposableStackResourcesType::kAllSync));
119 return ReadOnlyRoots(isolate).undefined_value();
120}
121
122BUILTIN(DisposableStackPrototypeGetDisposed) {
123 const char* const kMethodName = "get DisposableStack.prototype.disposed";
124 HandleScope scope(isolate);
125
126 // 1. Let disposableStack be the this value.
127 // 2. Perform ? RequireInternalSlot(disposableStack, [[DisposableState]]).
128 CHECK_RECEIVER(JSSyncDisposableStack, disposable_stack, kMethodName);
129
130 // 3. If disposableStack.[[DisposableState]] is disposed, return true.
131 if (disposable_stack->state() == DisposableStackState::kDisposed) {
132 return ReadOnlyRoots(isolate).true_value();
133 }
134 // 4. Otherwise, return false.
135 return ReadOnlyRoots(isolate).false_value();
136}
137
138// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-disposablestack.prototype.adopt
139BUILTIN(DisposableStackPrototypeAdopt) {
140 const char* const kMethodName = "DisposableStack.prototype.adopt";
141 HandleScope scope(isolate);
142 DirectHandle<Object> value = args.at(1);
143 DirectHandle<Object> on_dispose = args.at(2);
144
145 // 1. Let disposableStack be the this value.
146 // 2. Perform ? RequireInternalSlot(disposableStack, [[DisposableState]]).
147 CHECK_RECEIVER(JSSyncDisposableStack, disposable_stack, kMethodName);
148
149 // 3. If disposableStack.[[DisposableState]] is disposed, throw a
150 // ReferenceError exception.
151 if (disposable_stack->state() == DisposableStackState::kDisposed) {
153 isolate,
154 NewReferenceError(
155 MessageTemplate::kDisposableStackIsDisposed,
156 isolate->factory()->NewStringFromAsciiChecked(kMethodName)));
157 }
158
159 // 4. If IsCallable(onDispose) is false, throw a TypeError exception.
160 if (!IsCallable(*on_dispose)) {
162 isolate, NewTypeError(MessageTemplate::kNotCallable, on_dispose));
163 }
164
165 // 5. Let closure be a new Abstract Closure with no parameters that captures
166 // value and onDispose and performs the following steps when called:
167 // a. Return ? Call(onDispose, undefined, « value »).
168 // 6. Let F be CreateBuiltinFunction(closure, 0, "", « »).
169 // 7. Perform ? AddDisposableResource(disposableStack.[[DisposeCapability]],
170 // undefined, sync-dispose, F).
171 // Instead of creating an abstract closure and a function, we pass
172 // DisposeMethodCallType::kArgument so at the time of disposal, the value will
173 // be passed as the argument to the method.
174 JSDisposableStackBase::Add(isolate, disposable_stack, value, on_dispose,
177
178 // 8. Return value.
179 return *value;
180}
181
182// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-disposablestack.prototype.defer
183BUILTIN(DisposableStackPrototypeDefer) {
184 const char* const kMethodName = "DisposableStack.prototype.defer";
185 HandleScope scope(isolate);
186 DirectHandle<Object> on_dispose = args.at(1);
187
188 // 1. Let disposableStack be the this value.
189 // 2. Perform ? RequireInternalSlot(disposableStack, [[DisposableState]]).
190 CHECK_RECEIVER(JSSyncDisposableStack, disposable_stack, kMethodName);
191
192 // 3. If disposableStack.[[DisposableState]] is disposed, throw a
193 // ReferenceError exception.
194 if (disposable_stack->state() == DisposableStackState::kDisposed) {
196 isolate,
197 NewReferenceError(
198 MessageTemplate::kDisposableStackIsDisposed,
199 isolate->factory()->NewStringFromAsciiChecked(kMethodName)));
200 }
201
202 // 4. If IsCallable(onDispose) is false, throw a TypeError exception.
203 if (!IsCallable(*on_dispose)) {
205 isolate, NewTypeError(MessageTemplate::kNotCallable, on_dispose));
206 }
207
208 // 5. Perform ? AddDisposableResource(disposableStack.[[DisposeCapability]],
209 // undefined, sync-dispose, onDispose).
210 JSDisposableStackBase::Add(isolate, disposable_stack,
211 isolate->factory()->undefined_value(), on_dispose,
214
215 // 6. Return undefined.
216 return ReadOnlyRoots(isolate).undefined_value();
217}
218
219BUILTIN(DisposableStackPrototypeMove) {
220 const char* const kMethodName = "DisposableStack.prototype.move";
221 HandleScope scope(isolate);
222
223 // 1. Let disposableStack be the this value.
224 // 2. Perform ? RequireInternalSlot(disposableStack, [[DisposableState]]).
225 CHECK_RECEIVER(JSSyncDisposableStack, disposable_stack, kMethodName);
226
227 // 3. If disposableStack.[[DisposableState]] is disposed, throw a
228 // ReferenceError exception.
229 if (disposable_stack->state() == DisposableStackState::kDisposed) {
231 isolate,
232 NewReferenceError(
233 MessageTemplate::kDisposableStackIsDisposed,
234 isolate->factory()->NewStringFromAsciiChecked(kMethodName)));
235 }
236
237 // 4. Let newDisposableStack be ?
238 // OrdinaryCreateFromConstructor(%DisposableStack%,
239 // "%DisposableStack.prototype%", « [[DisposableState]],
240 // [[DisposeCapability]] »).
241 // 5. Set newDisposableStack.[[DisposableState]] to pending.
242
243 Tagged<JSFunction> constructor_function =
244 Cast<JSFunction>(isolate->native_context()->get(
245 Context::JS_DISPOSABLE_STACK_FUNCTION_INDEX));
246 DirectHandle<Map> map(constructor_function->initial_map(), isolate);
247
248 DirectHandle<JSSyncDisposableStack> new_disposable_stack =
249 isolate->factory()->NewJSSyncDisposableStack(map);
250
251 // 6. Set newDisposableStack.[[DisposeCapability]] to
252 // disposableStack.[[DisposeCapability]].
253 new_disposable_stack->set_stack(disposable_stack->stack());
254 new_disposable_stack->set_length(disposable_stack->length());
255 new_disposable_stack->set_state(DisposableStackState::kPending);
256 new_disposable_stack->set_error(*(isolate->factory()->uninitialized_value()));
257 new_disposable_stack->set_error_message(
258 *(isolate->factory()->uninitialized_value()));
259
260 // 7. Set disposableStack.[[DisposeCapability]] to NewDisposeCapability().
261 disposable_stack->set_stack(ReadOnlyRoots(isolate).empty_fixed_array());
262 disposable_stack->set_length(0);
263 disposable_stack->set_error(*(isolate->factory()->uninitialized_value()));
264 disposable_stack->set_error_message(
265 *(isolate->factory()->uninitialized_value()));
266
267 // 8. Set disposableStack.[[DisposableState]] to disposed.
268 disposable_stack->set_state(DisposableStackState::kDisposed);
269
270 // 9. Return newDisposableStack.
271 return *new_disposable_stack;
272}
273
274} // namespace internal
275} // namespace v8
#define CHECK_RECEIVER(Type, name, method)
#define BUILTIN(name)
@ kExplicitResourceManagement
Definition v8-isolate.h:635
static void InitializeJSDisposableStackBase(Isolate *isolate, DirectHandle< JSDisposableStackBase > stack)
Definition objects.cc:6384
static MaybeDirectHandle< Object > DisposeResources(Isolate *isolate, DirectHandle< JSDisposableStackBase > disposable_stack, DisposableStackResourcesType resources_type)
static void Add(Isolate *isolate, DirectHandle< JSDisposableStackBase > disposable_stack, DirectHandle< Object > value, DirectHandle< Object > method, DisposeMethodCallType type, DisposeMethodHint hint)
static MaybeDirectHandle< Object > CheckValueAndGetDisposeMethod(Isolate *isolate, DirectHandle< JSAny > value, DisposeMethodHint hint)
static V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT MaybeHandle< Map > GetDerivedMap(Isolate *isolate, DirectHandle< JSFunction > constructor, DirectHandle< JSReceiver > new_target)
#define ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call)
Definition isolate.h:284
#define THROW_NEW_ERROR_RETURN_FAILURE(isolate, call)
Definition isolate.h:294
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
DirectHandle< Object > new_target
Definition execution.cc:75
std::map< const std::string, const std::string > map
ZoneVector< RpoNumber > & result
bool IsNullOrUndefined(Tagged< Object > obj, Isolate *isolate)
return value
Definition map-inl.h:893
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
Symbol method