char/avril

(wip) why'd you have to go and make things so complicaaaaated?

git clone https://git.t4t.associates/char/avril

Charlotte Somharden internal promises and subclass constructors against guest tamperingfdaf84e

main
1.6 KiB50 linesraw
1import { Promise } from "ext:core/primordials";
2import { markPromiseHandled, performPromiseThen } from "ext:core/promise_hooks";
3import { isPromise } from "ext:core/event_hooks";
4
5// A thenable avoids Await's PromiseResolve constructor lookup without changing the source.
6export function safePromise(value) {
7  if (!isPromise(value)) return value;
8  return {
9    __proto__: null,
10    then(resolve, reject) {
11      performPromiseThen(value, resolve, reject);
12    },
13  };
14}
15export function newPromise(executor) {
16  return new Promise((resolve, reject) =>
17    executor((value) => resolve(safePromise(value)), reject)
18  );
19}
20export function promiseResolve(value) {
21  return newPromise((resolve) => resolve(value));
22}
23export function promiseReject(reason) {
24  return newPromise((_resolve, reject) => reject(reason));
25}
26export function promiseThen(promise, fulfilled, rejected) {
27  return performPromiseThen(
28    isPromise(promise) ? promise : promiseResolve(promise),
29    (value) =>
30      safePromise(typeof fulfilled === "function" ? fulfilled(value) : value),
31    (error) => {
32      if (typeof rejected === "function") return safePromise(rejected(error));
33      throw error;
34    },
35  );
36}
37export function promiseAll(values) {
38  return newPromise((resolve, reject) => {
39    const results = [], count = values.length;
40    let remaining = count;
41    if (!remaining) resolve(results);
42    for (let index = 0; index < count; index++) {
43      promiseThen(promiseResolve(values[index]), (value) => {
44        results[index] = value;
45        if (!--remaining) resolve(results);
46      }, reject);
47    }
48  });
49}
50export { markPromiseHandled };