Serenity Operating System
1/*
2 * Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <AK/Function.h>
8#include <LibJS/Interpreter.h>
9#include <LibJS/Runtime/AbstractOperations.h>
10#include <LibJS/Runtime/AggregateError.h>
11#include <LibJS/Runtime/Array.h>
12#include <LibJS/Runtime/Error.h>
13#include <LibJS/Runtime/FunctionObject.h>
14#include <LibJS/Runtime/GlobalObject.h>
15#include <LibJS/Runtime/IteratorOperations.h>
16#include <LibJS/Runtime/Promise.h>
17#include <LibJS/Runtime/PromiseCapability.h>
18#include <LibJS/Runtime/PromiseConstructor.h>
19#include <LibJS/Runtime/PromiseResolvingElementFunctions.h>
20
21namespace JS {
22
23// 27.2.4.1.1 GetPromiseResolve ( promiseConstructor ), https://tc39.es/ecma262/#sec-getpromiseresolve
24static ThrowCompletionOr<Value> get_promise_resolve(VM& vm, Value constructor)
25{
26 VERIFY(constructor.is_constructor());
27
28 // 1. Let promiseResolve be ? Get(promiseConstructor, "resolve").
29 auto promise_resolve = TRY(constructor.get(vm, vm.names.resolve));
30
31 // 2. If IsCallable(promiseResolve) is false, throw a TypeError exception.
32 if (!promise_resolve.is_function())
33 return vm.throw_completion<TypeError>(ErrorType::NotAFunction, TRY_OR_THROW_OOM(vm, promise_resolve.to_string_without_side_effects()));
34
35 // 3. Return promiseResolve.
36 return promise_resolve;
37}
38
39using EndOfElementsCallback = Function<ThrowCompletionOr<Value>(PromiseValueList&)>;
40using InvokeElementFunctionCallback = Function<ThrowCompletionOr<Value>(PromiseValueList&, RemainingElements&, Value, size_t)>;
41
42static ThrowCompletionOr<Value> perform_promise_common(VM& vm, Iterator& iterator_record, Value constructor, PromiseCapability const& result_capability, Value promise_resolve, EndOfElementsCallback end_of_list, InvokeElementFunctionCallback invoke_element_function)
43{
44 VERIFY(constructor.is_constructor());
45 VERIFY(promise_resolve.is_function());
46
47 // 1. Let values be a new empty List.
48 auto values = vm.heap().allocate_without_realm<PromiseValueList>();
49
50 // 2. Let remainingElementsCount be the Record { [[Value]]: 1 }.
51 auto remaining_elements_count = vm.heap().allocate_without_realm<RemainingElements>(1);
52
53 // 3. Let index be 0.
54 size_t index = 0;
55
56 // 4. Repeat,
57 while (true) {
58 // a. Let next be Completion(IteratorStep(iteratorRecord)).
59 auto next_or_error = iterator_step(vm, iterator_record);
60
61 // b. If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
62 // c. ReturnIfAbrupt(next).
63 if (next_or_error.is_throw_completion()) {
64 iterator_record.done = true;
65 return next_or_error.release_error();
66 }
67 auto* next = next_or_error.release_value();
68
69 // d. If next is false, then
70 if (!next) {
71 // i. Set iteratorRecord.[[Done]] to true.
72 iterator_record.done = true;
73
74 // ii. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
75 // iii. If remainingElementsCount.[[Value]] is 0, then
76 if (--remaining_elements_count->value == 0) {
77 // 1-2/3. are handled in `end_of_list`
78 return TRY(end_of_list(*values));
79 }
80
81 // iv. Return resultCapability.[[Promise]].
82 return result_capability.promise();
83 }
84
85 // e. Let nextValue be Completion(IteratorValue(next)).
86 auto next_value_or_error = iterator_value(vm, *next);
87
88 // f. If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true.
89 // g. ReturnIfAbrupt(nextValue).
90 if (next_value_or_error.is_throw_completion()) {
91 iterator_record.done = true;
92 return next_value_or_error.release_error();
93 }
94 auto next_value = next_value_or_error.release_value();
95
96 // h. Append undefined to values.
97 values->values().append(js_undefined());
98
99 // i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »).
100 auto next_promise = TRY(call(vm, promise_resolve.as_function(), constructor, next_value));
101
102 // j-q. are handled in `invoke_element_function`
103
104 // r. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] + 1.
105 ++remaining_elements_count->value;
106
107 // s. Perform ? Invoke(nextPromise, "then", « ... »).
108 TRY(invoke_element_function(*values, *remaining_elements_count, next_promise, index));
109
110 // t. Set index to index + 1.
111 ++index;
112 }
113}
114
115// 27.2.4.1.2 PerformPromiseAll ( iteratorRecord, constructor, resultCapability, promiseResolve ), https://tc39.es/ecma262/#sec-performpromiseall
116static ThrowCompletionOr<Value> perform_promise_all(VM& vm, Iterator& iterator_record, Value constructor, PromiseCapability const& result_capability, Value promise_resolve)
117{
118 auto& realm = *vm.current_realm();
119
120 return perform_promise_common(
121 vm, iterator_record, constructor, result_capability, promise_resolve,
122 [&](PromiseValueList& values) -> ThrowCompletionOr<Value> {
123 // 1. Let valuesArray be CreateArrayFromList(values).
124 auto values_array = Array::create_from(realm, values.values());
125
126 // 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »).
127 TRY(call(vm, *result_capability.resolve(), js_undefined(), values_array));
128
129 // iv. Return resultCapability.[[Promise]].
130 return result_capability.promise();
131 },
132 [&](PromiseValueList& values, RemainingElements& remaining_elements_count, Value next_promise, size_t index) {
133 // j. Let steps be the algorithm steps defined in Promise.all Resolve Element Functions.
134 // k. Let length be the number of non-optional parameters of the function definition in Promise.all Resolve Element Functions.
135 // l. Let onFulfilled be CreateBuiltinFunction(steps, length, "", « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »).
136 // m. Set onFulfilled.[[AlreadyCalled]] to false.
137 // n. Set onFulfilled.[[Index]] to index.
138 // o. Set onFulfilled.[[Values]] to values.
139 // p. Set onFulfilled.[[Capability]] to resultCapability.
140 // q. Set onFulfilled.[[RemainingElements]] to remainingElementsCount.
141 auto on_fulfilled = PromiseAllResolveElementFunction::create(realm, index, values, result_capability, remaining_elements_count);
142 on_fulfilled->define_direct_property(vm.names.name, PrimitiveString::create(vm, String {}), Attribute::Configurable);
143
144 // s. Perform ? Invoke(nextPromise, "then", « onFulfilled, resultCapability.[[Reject]] »).
145 return next_promise.invoke(vm, vm.names.then, on_fulfilled, result_capability.reject());
146 });
147}
148
149// 27.2.4.2.1 PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability, promiseResolve ), https://tc39.es/ecma262/#sec-performpromiseallsettled
150static ThrowCompletionOr<Value> perform_promise_all_settled(VM& vm, Iterator& iterator_record, Value constructor, PromiseCapability const& result_capability, Value promise_resolve)
151{
152 auto& realm = *vm.current_realm();
153
154 return perform_promise_common(
155 vm, iterator_record, constructor, result_capability, promise_resolve,
156 [&](PromiseValueList& values) -> ThrowCompletionOr<Value> {
157 auto values_array = Array::create_from(realm, values.values());
158
159 TRY(call(vm, *result_capability.resolve(), js_undefined(), values_array));
160
161 return result_capability.promise();
162 },
163 [&](PromiseValueList& values, RemainingElements& remaining_elements_count, Value next_promise, size_t index) {
164 // j. Let stepsFulfilled be the algorithm steps defined in Promise.allSettled Resolve Element Functions.
165 // k. Let lengthFulfilled be the number of non-optional parameters of the function definition in Promise.allSettled Resolve Element Functions.
166 // l. Let onFulfilled be CreateBuiltinFunction(stepsFulfilled, lengthFulfilled, "", « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »).
167 // m. Let alreadyCalled be the Record { [[Value]]: false }.
168 // n. Set onFulfilled.[[AlreadyCalled]] to alreadyCalled.
169 // o. Set onFulfilled.[[Index]] to index.
170 // p. Set onFulfilled.[[Values]] to values.
171 // q. Set onFulfilled.[[Capability]] to resultCapability.
172 // r. Set onFulfilled.[[RemainingElements]] to remainingElementsCount.
173 auto on_fulfilled = PromiseAllSettledResolveElementFunction::create(realm, index, values, result_capability, remaining_elements_count);
174 on_fulfilled->define_direct_property(vm.names.name, PrimitiveString::create(vm, String {}), Attribute::Configurable);
175
176 // s. Let stepsRejected be the algorithm steps defined in Promise.allSettled Reject Element Functions.
177 // t. Let lengthRejected be the number of non-optional parameters of the function definition in Promise.allSettled Reject Element Functions.
178 // u. Let onRejected be CreateBuiltinFunction(stepsRejected, lengthRejected, "", « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »).
179 // v. Set onRejected.[[AlreadyCalled]] to alreadyCalled.
180 // w. Set onRejected.[[Index]] to index.
181 // x. Set onRejected.[[Values]] to values.
182 // y. Set onRejected.[[Capability]] to resultCapability.
183 // z. Set onRejected.[[RemainingElements]] to remainingElementsCount.
184 auto on_rejected = PromiseAllSettledRejectElementFunction::create(realm, index, values, result_capability, remaining_elements_count);
185 on_rejected->define_direct_property(vm.names.name, PrimitiveString::create(vm, String {}), Attribute::Configurable);
186
187 // ab. Perform ? Invoke(nextPromise, "then", « onFulfilled, onRejected »).
188 return next_promise.invoke(vm, vm.names.then, on_fulfilled, on_rejected);
189 });
190}
191
192// 27.2.4.3.1 PerformPromiseAny ( iteratorRecord, constructor, resultCapability, promiseResolve ), https://tc39.es/ecma262/#sec-performpromiseany
193static ThrowCompletionOr<Value> perform_promise_any(VM& vm, Iterator& iterator_record, Value constructor, PromiseCapability& result_capability, Value promise_resolve)
194{
195 auto& realm = *vm.current_realm();
196
197 return perform_promise_common(
198 vm, iterator_record, constructor, result_capability, promise_resolve,
199 [&](PromiseValueList& errors) -> ThrowCompletionOr<Value> {
200 // 1. Let error be a newly created AggregateError object.
201 auto error = AggregateError::create(realm);
202
203 // 2. Perform ! DefinePropertyOrThrow(error, "errors", PropertyDescriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: CreateArrayFromList(errors) }).
204 auto errors_array = Array::create_from(realm, errors.values());
205 MUST(error->define_property_or_throw(vm.names.errors, { .value = errors_array, .writable = true, .enumerable = false, .configurable = true }));
206
207 // 3. Return ThrowCompletion(error).
208 return throw_completion(error);
209 },
210 [&](PromiseValueList& errors, RemainingElements& remaining_elements_count, Value next_promise, size_t index) {
211 // j. Let stepsRejected be the algorithm steps defined in Promise.any Reject Element Functions.
212 // k. Let lengthRejected be the number of non-optional parameters of the function definition in Promise.any Reject Element Functions.
213 // l. Let onRejected be CreateBuiltinFunction(stepsRejected, lengthRejected, "", « [[AlreadyCalled]], [[Index]], [[Errors]], [[Capability]], [[RemainingElements]] »).
214 // m. Set onRejected.[[AlreadyCalled]] to false.
215 // n. Set onRejected.[[Index]] to index.
216 // o. Set onRejected.[[Errors]] to errors.
217 // p. Set onRejected.[[Capability]] to resultCapability.
218 // q. Set onRejected.[[RemainingElements]] to remainingElementsCount.
219 auto on_rejected = PromiseAnyRejectElementFunction::create(realm, index, errors, result_capability, remaining_elements_count);
220 on_rejected->define_direct_property(vm.names.name, PrimitiveString::create(vm, String {}), Attribute::Configurable);
221
222 // s. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], onRejected »).
223 return next_promise.invoke(vm, vm.names.then, result_capability.resolve(), on_rejected);
224 });
225}
226
227// 27.2.4.5.1 PerformPromiseRace ( iteratorRecord, constructor, resultCapability, promiseResolve ), https://tc39.es/ecma262/#sec-performpromiserace
228static ThrowCompletionOr<Value> perform_promise_race(VM& vm, Iterator& iterator_record, Value constructor, PromiseCapability const& result_capability, Value promise_resolve)
229{
230 return perform_promise_common(
231 vm, iterator_record, constructor, result_capability, promise_resolve,
232 [&](PromiseValueList&) -> ThrowCompletionOr<Value> {
233 // ii. Return resultCapability.[[Promise]].
234 return result_capability.promise();
235 },
236 [&](PromiseValueList&, RemainingElements&, Value next_promise, size_t) {
237 // i. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »).
238 return next_promise.invoke(vm, vm.names.then, result_capability.resolve(), result_capability.reject());
239 });
240}
241
242PromiseConstructor::PromiseConstructor(Realm& realm)
243 : NativeFunction(realm.vm().names.Promise.as_string(), *realm.intrinsics().function_prototype())
244{
245}
246
247ThrowCompletionOr<void> PromiseConstructor::initialize(Realm& realm)
248{
249 auto& vm = this->vm();
250 MUST_OR_THROW_OOM(NativeFunction::initialize(realm));
251
252 // 27.2.4.4 Promise.prototype, https://tc39.es/ecma262/#sec-promise.prototype
253 define_direct_property(vm.names.prototype, realm.intrinsics().promise_prototype(), 0);
254
255 u8 attr = Attribute::Writable | Attribute::Configurable;
256 define_native_function(realm, vm.names.all, all, 1, attr);
257 define_native_function(realm, vm.names.allSettled, all_settled, 1, attr);
258 define_native_function(realm, vm.names.any, any, 1, attr);
259 define_native_function(realm, vm.names.race, race, 1, attr);
260 define_native_function(realm, vm.names.reject, reject, 1, attr);
261 define_native_function(realm, vm.names.resolve, resolve, 1, attr);
262
263 define_native_accessor(realm, *vm.well_known_symbol_species(), symbol_species_getter, {}, Attribute::Configurable);
264
265 define_direct_property(vm.names.length, Value(1), Attribute::Configurable);
266
267 return {};
268}
269
270// 27.2.3.1 Promise ( executor ), https://tc39.es/ecma262/#sec-promise-executor
271ThrowCompletionOr<Value> PromiseConstructor::call()
272{
273 auto& vm = this->vm();
274
275 // 1. If NewTarget is undefined, throw a TypeError exception.
276 return vm.throw_completion<TypeError>(ErrorType::ConstructorWithoutNew, vm.names.Promise);
277}
278
279// 27.2.3.1 Promise ( executor ), https://tc39.es/ecma262/#sec-promise-executor
280ThrowCompletionOr<NonnullGCPtr<Object>> PromiseConstructor::construct(FunctionObject& new_target)
281{
282 auto& vm = this->vm();
283
284 auto executor = vm.argument(0);
285
286 // 2. If IsCallable(executor) is false, throw a TypeError exception.
287 if (!executor.is_function())
288 return vm.throw_completion<TypeError>(ErrorType::PromiseExecutorNotAFunction);
289
290 // 3. Let promise be ? OrdinaryCreateFromConstructor(NewTarget, "%Promise.prototype%", « [[PromiseState]], [[PromiseResult]], [[PromiseFulfillReactions]], [[PromiseRejectReactions]], [[PromiseIsHandled]] »).
291 // 4. Set promise.[[PromiseState]] to pending.
292 // 5. Set promise.[[PromiseFulfillReactions]] to a new empty List.
293 // 6. Set promise.[[PromiseRejectReactions]] to a new empty List.
294 // 7. Set promise.[[PromiseIsHandled]] to false.
295 auto promise = TRY(ordinary_create_from_constructor<Promise>(vm, new_target, &Intrinsics::promise_prototype));
296
297 // 8. Let resolvingFunctions be CreateResolvingFunctions(promise).
298 auto [resolve_function, reject_function] = promise->create_resolving_functions();
299
300 // 9. Let completion be Completion(Call(executor, undefined, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »)).
301 auto completion = JS::call(vm, executor.as_function(), js_undefined(), &resolve_function, &reject_function);
302
303 // 10. If completion is an abrupt completion, then
304 if (completion.is_error()) {
305 // a. Perform ? Call(resolvingFunctions.[[Reject]], undefined, « completion.[[Value]] »).
306 TRY(JS::call(vm, reject_function, js_undefined(), *completion.release_error().value()));
307 }
308
309 // 11. Return promise.
310 return promise;
311}
312
313// 27.2.4.1 Promise.all ( iterable ), https://tc39.es/ecma262/#sec-promise.all
314JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::all)
315{
316 // 1. Let C be the this value.
317 auto* constructor = TRY(vm.this_value().to_object(vm));
318
319 // 2. Let promiseCapability be ? NewPromiseCapability(C).
320 auto promise_capability = TRY(new_promise_capability(vm, constructor));
321
322 // 3. Let promiseResolve be Completion(GetPromiseResolve(C)).
323 // 4. IfAbruptRejectPromise(promiseResolve, promiseCapability).
324 auto promise_resolve = TRY_OR_REJECT(vm, promise_capability, get_promise_resolve(vm, constructor));
325
326 // 5. Let iteratorRecord be Completion(GetIterator(iterable)).
327 // 6. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
328 auto iterator_record = TRY_OR_REJECT(vm, promise_capability, get_iterator(vm, vm.argument(0)));
329
330 // 7. Let result be Completion(PerformPromiseAll(iteratorRecord, C, promiseCapability, promiseResolve)).
331 auto result = perform_promise_all(vm, iterator_record, constructor, promise_capability, promise_resolve);
332
333 // 8. If result is an abrupt completion, then
334 if (result.is_error()) {
335 // a. If iteratorRecord.[[Done]] is false, set result to Completion(IteratorClose(iteratorRecord, result)).
336 if (!iterator_record.done)
337 result = iterator_close(vm, iterator_record, result.release_error());
338
339 // b. IfAbruptRejectPromise(result, promiseCapability).
340 TRY_OR_REJECT(vm, promise_capability, result);
341 }
342
343 // 9. Return ? result.
344 return result;
345}
346
347// 27.2.4.2 Promise.allSettled ( iterable ), https://tc39.es/ecma262/#sec-promise.allsettled
348JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::all_settled)
349{
350 // 1. Let C be the this value.
351 auto* constructor = TRY(vm.this_value().to_object(vm));
352
353 // 2. Let promiseCapability be ? NewPromiseCapability(C).
354 auto promise_capability = TRY(new_promise_capability(vm, constructor));
355
356 // 3. Let promiseResolve be Completion(GetPromiseResolve(C)).
357 // 4. IfAbruptRejectPromise(promiseResolve, promiseCapability).
358 auto promise_resolve = TRY_OR_REJECT(vm, promise_capability, get_promise_resolve(vm, constructor));
359
360 // 5. Let iteratorRecord be Completion(GetIterator(iterable)).
361 // 6. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
362 auto iterator_record = TRY_OR_REJECT(vm, promise_capability, get_iterator(vm, vm.argument(0)));
363
364 // 7. Let result be Completion(PerformPromiseAllSettled(iteratorRecord, C, promiseCapability, promiseResolve)).
365 auto result = perform_promise_all_settled(vm, iterator_record, constructor, promise_capability, promise_resolve);
366
367 // 8. If result is an abrupt completion, then
368 if (result.is_error()) {
369 // a. If iteratorRecord.[[Done]] is false, set result to Completion(IteratorClose(iteratorRecord, result)).
370 if (!iterator_record.done)
371 result = iterator_close(vm, iterator_record, result.release_error());
372
373 // b. IfAbruptRejectPromise(result, promiseCapability).
374 TRY_OR_REJECT(vm, promise_capability, result);
375 }
376
377 // 9. Return ? result.
378 return result;
379}
380
381// 27.2.4.3 Promise.any ( iterable ), https://tc39.es/ecma262/#sec-promise.any
382JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::any)
383{
384 // 1. Let C be the this value.
385 auto* constructor = TRY(vm.this_value().to_object(vm));
386
387 // 2. Let promiseCapability be ? NewPromiseCapability(C).
388 auto promise_capability = TRY(new_promise_capability(vm, constructor));
389
390 // 3. Let promiseResolve be Completion(GetPromiseResolve(C)).
391 // 4. IfAbruptRejectPromise(promiseResolve, promiseCapability).
392 auto promise_resolve = TRY_OR_REJECT(vm, promise_capability, get_promise_resolve(vm, constructor));
393
394 // 5. Let iteratorRecord be Completion(GetIterator(iterable)).
395 // 6. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
396 auto iterator_record = TRY_OR_REJECT(vm, promise_capability, get_iterator(vm, vm.argument(0)));
397
398 // 7. Let result be Completion(PerformPromiseAny(iteratorRecord, C, promiseCapability, promiseResolve)).
399 auto result = perform_promise_any(vm, iterator_record, constructor, promise_capability, promise_resolve);
400
401 // 8. If result is an abrupt completion, then
402 if (result.is_error()) {
403 // a. If iteratorRecord.[[Done]] is false, set result to Completion(IteratorClose(iteratorRecord, result)).
404 if (!iterator_record.done)
405 result = iterator_close(vm, iterator_record, result.release_error());
406
407 // b. IfAbruptRejectPromise(result, promiseCapability).
408 TRY_OR_REJECT(vm, promise_capability, result);
409 }
410
411 // 9. Return ? result.
412 return result;
413}
414
415// 27.2.4.5 Promise.race ( iterable ), https://tc39.es/ecma262/#sec-promise.race
416JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::race)
417{
418 // 1. Let C be the this value.
419 auto* constructor = TRY(vm.this_value().to_object(vm));
420
421 // 2. Let promiseCapability be ? NewPromiseCapability(C).
422 auto promise_capability = TRY(new_promise_capability(vm, constructor));
423
424 // 3. Let promiseResolve be Completion(GetPromiseResolve(C)).
425 // 4. IfAbruptRejectPromise(promiseResolve, promiseCapability).
426 auto promise_resolve = TRY_OR_REJECT(vm, promise_capability, get_promise_resolve(vm, constructor));
427
428 // 5. Let iteratorRecord be Completion(GetIterator(iterable)).
429 // 6. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
430 auto iterator_record = TRY_OR_REJECT(vm, promise_capability, get_iterator(vm, vm.argument(0)));
431
432 // 7. Let result be Completion(PerformPromiseRace(iteratorRecord, C, promiseCapability, promiseResolve)).
433 auto result = perform_promise_race(vm, iterator_record, constructor, promise_capability, promise_resolve);
434
435 // 8. If result is an abrupt completion, then
436 if (result.is_error()) {
437 // a. If iteratorRecord.[[Done]] is false, set result to Completion(IteratorClose(iteratorRecord, result)).
438 if (!iterator_record.done)
439 result = iterator_close(vm, iterator_record, result.release_error());
440
441 // b. IfAbruptRejectPromise(result, promiseCapability).
442 TRY_OR_REJECT(vm, promise_capability, result);
443 }
444
445 // 9. Return ? result.
446 return result;
447}
448
449// 27.2.4.6 Promise.reject ( r ), https://tc39.es/ecma262/#sec-promise.reject
450JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::reject)
451{
452 auto reason = vm.argument(0);
453
454 // 1. Let C be the this value.
455 auto* constructor = TRY(vm.this_value().to_object(vm));
456
457 // 2. Let promiseCapability be ? NewPromiseCapability(C).
458 auto promise_capability = TRY(new_promise_capability(vm, constructor));
459
460 // 3. Perform ? Call(promiseCapability.[[Reject]], undefined, « r »).
461 [[maybe_unused]] auto result = TRY(JS::call(vm, *promise_capability->reject(), js_undefined(), reason));
462
463 // 4. Return promiseCapability.[[Promise]].
464 return promise_capability->promise();
465}
466
467// 27.2.4.7 Promise.resolve ( x ), https://tc39.es/ecma262/#sec-promise.resolve
468JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::resolve)
469{
470 auto value = vm.argument(0);
471
472 // 1. Let C be the this value.
473 auto constructor = vm.this_value();
474
475 // 2. If Type(C) is not Object, throw a TypeError exception.
476 if (!constructor.is_object())
477 return vm.throw_completion<TypeError>(ErrorType::NotAnObject, TRY_OR_THROW_OOM(vm, constructor.to_string_without_side_effects()));
478
479 // 3. Return ? PromiseResolve(C, x).
480 return TRY(promise_resolve(vm, constructor.as_object(), value));
481}
482
483// 27.2.4.8 get Promise [ @@species ], https://tc39.es/ecma262/#sec-get-promise-@@species
484JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::symbol_species_getter)
485{
486 // 1. Return the this value.
487 return vm.this_value();
488}
489
490}