// |jit-test| skip-if: getBuildConfiguration("release_or_beta") // // JS::SafeResolve: promise-like and non-native-promise resolution values must // be handled via a deferred microtask, so that Get(resolution, "then") never // runs on the caller's stack.
// --------------------------------------------------------------------------- // Plain thenable with a callable data "then" property on the object itself.
{ const {promise} = Promise.withResolvers();
// --------------------------------------------------------------------------- // Thenable where "then" is an accessor (getter). Pure lookup can't read it; // SafeResolve must defer and the getter runs in the job, not synchronously.
{ const {promise} = Promise.withResolvers();
// --------------------------------------------------------------------------- // Thenable where "then" lives on the prototype (inherited). Must be treated // as callable and deferred.
{ const {promise} = Promise.withResolvers();
// --------------------------------------------------------------------------- // Proxy with a "then" trap. Proxies MUST force deferral regardless of trap // behavior, because any MOP access could run user code.
{ const {promise} = Promise.withResolvers();
let settled;
promise.then(v => { settled = v; });
drainJobQueue(); // In the microtask, Get(resolution, "then") happens exactly once, then the // assimilation job calls the returned function (a separate MOP access — // "get" trap is not invoked for calling a function already retrieved).
assertEq(log[0], "proxy-get:then");
assertEq(log[1], "proxy-then");
assertEq(settled, "proxy-value");
}
// --------------------------------------------------------------------------- // Revoked proxy: Get("then") throws. The rejection must happen in the job, // not synchronously.
{ const {promise} = Promise.withResolvers(); const {proxy, revoke} = Proxy.revocable({}, {});
revoke();
safeResolvePromise(promise, proxy);
let result = null;
promise.then(v => { result = {fulfilled: v}; },
e => { result = {rejected: e}; });
drainJobQueue();
assertEq(result !== null, true);
assertEq("rejected" in result, true);
}
// --------------------------------------------------------------------------- // Proxy whose "then" is NOT callable. Must still defer, then fulfill with the // object itself (because IsCallable(then) is false in PerformPromiseResolution).
{ const {promise} = Promise.withResolvers(); const target = {}; const proxy = new Proxy(target, {
get(t, name) { return name === "then" ? 42 : t[name]; },
});
safeResolvePromise(promise, proxy);
// --------------------------------------------------------------------------- // A real Promise as the resolution value, with an observable own "then" so we // can verify the call happens in the deferred job, not on the caller's stack.
{ const {promise} = Promise.withResolvers(); const inner = Promise.resolve("inner-value"); const observations = []; const originalThen = Promise.prototype.then;
Object.defineProperty(inner, "then", {
value: function(...args) {
observations.push("then-called"); return originalThen.apply(this, args);
},
writable: true, configurable: true,
});
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.