2025-08-01 [11:30:49.0200] > <@abotella:igalia.com> it'd be a shame to not have that be captured properly Isn't that the correct way to capture it in the notes? "This is ZTZ, also know as ZTZ or ZTZ online, but you can call him ZTZ". [11:42:52.0526] Where can I read the notes? [11:43:44.0922] they're linked in the Reflector issue 2025-08-04 [21:23:13.0255] ``` function safePromiseCapability() { let { promise, resolve, reject } = Promise.withResolvers(); function safeResolve(val) { Object.defineProperty(val, 'then', { configurable: true, value: void 0 }); resolve(val); delete val.then; } return { promise, safeResolve, reject }; } let evilProto = { get then() { throw 'boom'; } }; let { promise, safeResolve } = safePromiseCapability(); safeResolve({ __proto__: evilProto, key: 'value' }); console.log((await promise).key); // no boom ``` turns out we already have the "safe promise resolve" capability with no changes to the language [21:30:05.0182] I... don't understand how that's safe. Doesn't that override/delete a .then property on the element, potentially wiping out an existing .then property? [21:32:44.0862] sorry, yes, the assumption is that you are only using this with an object you've just created yourself [21:32:55.0296] and you're trying to avoid the problem where someone might have put a `.then` on Object.prototype [21:33:25.0614] * sorry, yes, the assumption is that you are only using this with an object you've just created yourself, which you know not to have such a property [21:35:00.0663] * ``` function safePromiseCapability() { let { promise, resolve, reject } = Promise.withResolvers(); function safeResolve(val) { if (Object.hasOwn(val, 'then')) throw new TypeError('you are not supposed to use this with thenables'); Object.defineProperty(val, 'then', { configurable: true, value: void 0 }); resolve(val); delete val.then; } return { promise, safeResolve, reject }; } let evilProto = { get then() { throw 'boom'; } }; let { promise, safeResolve } = safePromiseCapability(); safeResolve({ __proto__: evilProto, key: 'value' }); console.log((await promise).key); // no boom ``` turns out we already have the "safe promise resolve" capability with no changes to the language [03:54:46.0926] This example makes my concern about having `.then` being called with a thenable (and thus `.then(x => x)` not being an identity) moot, since it's already possible [08:27:51.0901] "only using this with an [unfrozen] object you've just created yourself" is an **enormous** restriction [08:32:34.0657] * "only using this with an \[extensible\] object you've just created yourself" is an **enormous** restriction [08:39:26.0867] TC39 your individual contributor RFTC license/permission form is so good I'm adapting it for all of Ecma [08:47:55.0650] Yes, but it's exactly the case that matters for the security problems in web specs that were presented [10:04:12.0467] I should say, basic idea is due to Justin Ridgewell https://github.com/tc39/proposal-thenable-curtailment/issues/5#issuecomment-3145520373 [10:06:03.0028] "extensible" isn't necessary since you can make it non-extensible after doing this step, but yes, still a pretty significant restriction. but as nicolo says it does cover most of the actual CVEs [10:06:55.0186] also the "just" created yourself can be dropped if you're willing to have it throw if the object has a `.then` property that the user put on it, which I think is a perfectly fine restriction; I updated my snippet to do that. as long as you know the object is one you created then you can rely on it not being a proxy and so the hasOwn check not triggering user code [10:07:30.0814] * also the "just" part of "just created yourself" can be dropped if you're willing to have it throw if the object has a `.then` property that the user put on it, which I think is a perfectly fine restriction; I updated my snippet to do that. as long as you know the object is one you created, even if you've since handed it out to a user (as in the Animation CVE in the repo) then you can rely on it not being a proxy and so the hasOwn check not triggering user code [10:12:56.0569] I wonder if we ought to do this for async iterator result objects https://github.com/tc39/Reflector/issues/535 [10:32:30.0054] There’s also the potential to introduce a `Fulfilled` wrapper which could short-circuit the resolution recursion. [10:34:22.0059] `await Promise.resolve(new Fulfilled(thenable)) === thenable`