Serenity Operating System
at master 490 lines 25 kB view raw
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}