Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  safe-resolve-thenables.js

  Sprache: JAVA
 

// |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();

  const observations = [];
  const thenable = {
     then(onFulfilled, onRejected) {
        observations.push("then-called");
        onFulfilled(42);
    },
  };

  safeResolvePromise(promise, thenable);
  // Neither the getter nor the returned function should be called.
  assertEq(observations.length, 0);

  let settled;
  promise.then(v => { settled = v; });
  drainJobQueue();
  assertEq(observations[0], "then-called");
  assertEq(settled, 42);
}

// ---------------------------------------------------------------------------
// 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();

  const log = [];
  const thenable = {
    get then() {
      log.push("get-then");
      return function(onFulfilled) {
        log.push("call-then");
        onFulfilled("from-getter");
      };
    },
  };

  safeResolvePromise(promise, thenable);
  // The getter must not have run yet.
  assertEq(log.length, 0);

  let settled;
  promise.then(v => { settled = v; });
  drainJobQueue();
  assertEq(log.join(","), "get-then,call-then");
  assertEq(settled, "from-getter");
}

// ---------------------------------------------------------------------------
// Thenable where "then" lives on the prototype (inherited). Must be treated
// as callable and deferred.
{
  const {promise} = Promise.withResolvers();

  const log = [];
  class Thenable {
    then(onFulfilled) {
      log.push("proto-then");
      onFulfilled("proto-value");
    }
  }
  const thenable = new Thenable();
  safeResolvePromise(promise, thenable);
  assertEq(log.length, 0);

  let settled;
  promise.then(v => { settled = v; });
  drainJobQueue();
  assertEq(log[0], "proto-then");
  assertEq(settled, "proto-value");
}

// ---------------------------------------------------------------------------
// 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();

  const log = [];
  const target = {};
  const handler = {
    get(t, name) {
      log.push("proxy-get:" + String(name));
      if (name === "then") {
        return function(onFulfilled) {
          log.push("proxy-then");
          onFulfilled("proxy-value");
        };
      }
      return t[name];
    },
  };
  const thenable = new Proxy(target, handler);
  safeResolvePromise(promise, thenable);
  // No MOP access should have happened yet.
  assertEq(log.length, 0);

  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 !== nulltrue);
  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);

  let settled;
  promise.then(v => { settled = v; });
  drainJobQueue();
  assertEq(settled, 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,
  });

  safeResolvePromise(promise, inner);
  assertEq(observations.length, 0);

  let settled;
  promise.then(v => { settled = v; });
  drainJobQueue();
  assertEq(observations[0], "then-called");
  assertEq(settled, "inner-value");
}

// ---------------------------------------------------------------------------
// Cross-compartment promise as the resolution value.
{
  const g = newGlobal({newCompartment: true});
  const {promise} = Promise.withResolvers();
  const inner = g.eval("Promise.resolve('cross-realm')");
  safeResolvePromise(promise, inner);

  let settled;
  promise.then(v => { settled = v; });
  drainJobQueue();
  assertEq(settled, "cross-realm");
}

Messung V0.5 in Prozent
C=85 H=100 G=92

¤ Dauer der Verarbeitung: 0.3 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002