CodeSampleX

Exemplo

happy-dom 20.11.2: Handle GlobalWindow host evaluation scope and Web API binding in happy-dom 20.11.2

Amostra verificada para npm happy-dom 20.11.2: Handle GlobalWindow host evaluation scope and Web API binding in happy-dom 20.11.2. O contrato rodou em node…

sha256:aa6e2d778756afb0c5266378a3bfb085859140bb2aeb2427304b453f73121483

Esta rede oferece uma coisa: uma amostra que compila. Ela a executou em um sandbox e guardou o recibo assinado. Não classifica nem garante nada — se o mesmo código compila onde você está, ela não mediu. Quantas chaves de assinatura distintas enviaram um recibo de contrato aprovado. Uma é só o autor; mais de uma significa que outra pessoa também o compilou. Uma chave é gerada por conta própria e não tem identidade registrada por trás, então conta chaves, não pessoas. MIT-0

Evidência de execução

O ambiente declarado e as execuções assinadas ficam separados, para você ver exatamente o que esta amostra executou e onde.

Base da evidência
Contrato assinado aprovado
Recibos de verificação
3
Chaves de assinatura que o compilaram
3
Ambiente declarado node linux x64 node node npm

Ambientes das execuções de verificação

Ambiente Contrato Etapas Execução
node 22 · linux alpine/x64 · docker ed25519:d91480838ac982c9 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-18
node 22 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-18
node 22 · linux alpine/x64 · docker ed25519:c1973797be207ac4 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1node:22-alpine@sha256:c610fcdfb1d5…
2026-09-07

Caso

HOW
Objetivo
Handle GlobalWindow host evaluation scope and Web API binding in happy-dom 20.11.2
Pacotes
Símbolos
  • GlobalWindow
Ambiente
node
Criado
2026-08-18T08:43:37Z

Contrato

  1. DOM scripts evaluated in GlobalWindow run in host globalThis without a VM context, causing unqualified window references to throw ReferenceError rather than resolving the window instance
  2. GlobalWindow shares host ECMAScript prototypes and constructors including Array, Object, and Promise with globalThis while Window uses a separate VM realm
  3. GlobalWindow preserves instance-bound Happy DOM implementations for Web platform APIs such as URL, Request, and setTimeout rather than replacing them with host Node globals
  4. happyDOM.waitUntilComplete waits for pending window-bound timers registered via GlobalWindow.prototype.setTimeout

Arquivos

  • NOTES.md
  • csx.json
  • package-lock.json
  • package.json
  • test/contract.mjs

Baixar o artefato de código-fonte (tar.gz)

Código-fonte

NOTES.md
# happy-dom 20.11.2 `GlobalWindow`

Prior lookup via solution search returned sample `sha256:c1bdb0ba279aeb6d85fbba5684c7ca243df831004f5adadade23ab33fa743f5a`, which established cross-realm constructor sharing and detached window teardown requirements.

This investigation examines the script evaluation scope and Web API partitioning of `GlobalWindow` on exact release `20.11.2`.

## Observed Behavior

`GlobalWindow` extends `Window` but overrides the internal VM context initialization method to be a no-op. It executes evaluated scripts directly using `globalThis.eval` in the host Node realm rather than creating a dedicated `node:vm` context.

1. **DOM Script Evaluation Scope**:
   When script evaluation is enabled (`settings: { enableJavaScriptEvaluation: true }`), scripts executed via DOM elements (such as `<script>window.foo = 1;</script>`) evaluate within Node's host global scope. Because `window` and `document` do not exist as globals on Node's `globalThis` by default, unqualified references to `window` throw `ReferenceError: window is not defined`.
   Under default browser settings (`errorCapture: 'tryAndCatch'`), this failure is caught and dispatched as an `ErrorEvent` on the window instance, leaving the script unexecuted without throwing an unhandled exception. Standard `Window`, by contrast, operates inside a VM context where `window` is the global object, allowing DOM scripts to reference `window` and `document` directly.

2. **Builtins vs Web API Split**:
   `GlobalWindow` assigns standard ECMAScript constructors (`Array`, `Object`, `Promise`, `Error`, `Buffer`) directly to Node's host globals, ensuring identical object identities across host code and library utilities. However, Web platform implementations (`URL`, `Request`, `Response`, `setTimeout`) remain Happy DOM's window-bound classes and methods (`window.URL !== globalThis.URL`).

3. **Asynchronous Task Lifecycle**:
   Timers scheduled through `GlobalWindow.prototype.setTimeout` are tracked by the window's async task manager. Calling `await window.happyDOM.waitUntilComplete()` resolves when all pending window-bound timers have completed.
csx.json
{"case":{"believed":"Evaluating scripts in a GlobalWindow executes in an isolated window context where bare window and document identifiers resolve to the instance.","caseId":"case:sha256:b6ac03bafd7f1a240018abbc05114f22209eb6a09b9a374f747e8574f055f9d6","contract":["DOM scripts evaluated in GlobalWindow run in host globalThis without a VM context, causing unqualified window references to throw ReferenceError rather than resolving the window instance","GlobalWindow shares host ECMAScript prototypes and constructors including Array, Object, and Promise with globalThis while Window uses a separate VM realm","GlobalWindow preserves instance-bound Happy DOM implementations for Web platform APIs such as URL, Request, and setTimeout rather than replacing them with host Node globals","happyDOM.waitUntilComplete waits for pending window-bound timers registered via GlobalWindow.prototype.setTimeout"],"goal":"Handle GlobalWindow host evaluation scope and Web API binding in happy-dom 20.11.2","kind":"HOW","packages":["pkg:npm/happy-dom@20.11.2"],"schemaVersion":1,"symbols":["GlobalWindow"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","ecosystem":"npm","executionContext":"node","language":"node","os":"linux","packageManager":"npm","runtime":"node","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/happy-dom@20.11.2"],"schemaVersion":1,"symbols":["GlobalWindow"],"verifierAdapter":"node-typescript@1"}
package-lock.json
{
  "name": "csx-sample-happy-dom-20112-globalwindow",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "csx-sample-happy-dom-20112-globalwindow",
      "version": "1.0.0",
      "dependencies": {
        "happy-dom": "20.11.2"
      }
    },
    "node_modules/@types/node": {
      "version": "26.2.0",
      "resolved": "https://registry.npmjs.org/@types/node/-/node-26.2.0.tgz",
      "integrity": "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg==",
      "license": "MIT",
      "dependencies": {
        "undici-types": "~8.3.0"
      }
    },
    "node_modules/@types/whatwg-mimetype": {
      "version": "3.0.2",
      "resolved": "https://registry.npmjs.org/@types/whatwg-mimetype/-/whatwg-mimetype-3.0.2.tgz",
      "integrity": "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==",
      "license": "MIT"
    },
    "node_modules/@types/ws": {
      "version": "8.18.1",
      "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
      "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
      "license": "MIT",
      "dependencies": {
        "@types/node": "*"
      }
    },
    "node_modules/buffer-image-size": {
      "version": "0.6.4",
      "resolved": "https://registry.npmjs.org/buffer-image-size/-/buffer-image-size-0.6.4.tgz",
      "integrity": "sha512-nEh+kZOPY1w+gcCMobZ6ETUp9WfibndnosbpwB1iJk/8Gt5ZF2bhS6+B6bPYz424KtwsR6Rflc3tCz1/ghX2dQ==",
      "license": "MIT",
      "dependencies": {
        "@types/node": "*"
      },
      "engines": {
        "node": ">=4.0"
      }
    },
    "node_modules/entities": {
      "version": "7.0.1",
      "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
      "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
      "license": "BSD-2-Clause",
      "engines": {
        "node": ">=0.12"
      },
      "funding": {
        "url": "https://github.com/fb55/entities?sponsor=1"
      }
    },
    "node_modules/happy-dom": {
      "version": "20.11.2",
      "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-20.11.2.tgz",
      "integrity": "sha512-7MB+bJLkxu3SowAfBJbjW+c55kNz5tkR45gu2qzrxznezhLeN5YIlJbwUgSzlGc+qWoZ8Ykg71H5ezz69xixrw==",
      "license": "MIT",
      "dependencies": {
        "@types/node": ">=20.0.0",
        "@types/whatwg-mimetype": "^3.0.2",
        "@types/ws": "^8.18.1",
        "buffer-image-size": "^0.6.4",
        "entities": "^7.0.1",
        "whatwg-mimetype": "^3.0.0",
        "ws": "^8.21.0"
      },
      "engines": {
        "node": ">=20.0.0"
      }
    },
    "node_modules/undici-types": {
      "version": "8.3.0",
      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz",
      "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==",
      "license": "MIT"
    },
    "node_modules/whatwg-mimetype": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz",
      "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==",
      "license": "MIT",
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/ws": {
      "version": "8.21.3",
      "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz",
      "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==",
      "license": "MIT",
      "engines": {
        "node": ">=10.0.0"
      },
      "peerDependencies": {
        "bufferutil": "^4.0.1",
        "utf-8-validate": ">=5.0.2"
      },
      "peerDependenciesMeta": {
        "bufferutil": {
          "optional": true
        },
        "utf-8-validate": {
          "optional": true
        }
      }
    }
  }
}
package.json
{
  "name": "csx-sample-happy-dom-20112-globalwindow",
  "version": "1.0.0",
  "private": true,
  "type": "module",
  "scripts": {
    "test": "node test/contract.mjs"
  },
  "dependencies": {
    "happy-dom": "20.11.2"
  }
}
test/contract.mjs
import assert from "node:assert/strict";
import vm from "node:vm";
import { GlobalWindow, Window } from "happy-dom";

const settings = {
  enableJavaScriptEvaluation: true,
  suppressInsecureJavaScriptEnvironmentWarning: true,
};

const gw = new GlobalWindow({ url: "https://example.com/", settings });
const isolated = new Window({ url: "https://example.com/", settings });

try {
  // 1. Script evaluation scope in GlobalWindow vs Window
  // GlobalWindow skips setupVMContext and runs scripts in host globalThis.eval.
  // In Node host scope, unqualified 'window' is not defined, triggering ReferenceError.
  let capturedGwError = null;
  gw.addEventListener("error", (event) => {
    capturedGwError = event.error;
  });

  const scriptGw = gw.document.createElement("script");
  scriptGw.textContent = "window.__script_executed = true;";
  gw.document.body.appendChild(scriptGw);

  assert.ok(capturedGwError instanceof ReferenceError);
  assert.match(capturedGwError.message, /window is not defined/);
  assert.equal(gw.__script_executed, undefined);

  // In Window, VM context is established and 'window' resolves to the Window instance
  let capturedIsolatedError = null;
  isolated.addEventListener("error", (event) => {
    capturedIsolatedError = event.error;
  });

  const scriptIsolated = isolated.document.createElement("script");
  scriptIsolated.textContent = "window.__script_executed = true;";
  isolated.document.body.appendChild(scriptIsolated);

  assert.equal(capturedIsolatedError, null);
  assert.equal(isolated.__script_executed, true);

  // 2. Global ECMAScript intrinsics vs VM realm isolation
  assert.equal(vm.isContext(gw), false);
  assert.equal(vm.isContext(isolated), true);
  assert.equal(gw.Array, globalThis.Array);
  assert.equal(gw.Promise, globalThis.Promise);
  assert.equal(gw.Object, globalThis.Object);
  assert.notEqual(isolated.Array, globalThis.Array);
  assert.notEqual(isolated.Promise, globalThis.Promise);

  // 3. Web Platform APIs remain Happy DOM instance-bound implementations
  assert.notEqual(gw.URL, globalThis.URL);
  assert.notEqual(gw.Request, globalThis.Request);
  assert.notEqual(gw.setTimeout, globalThis.setTimeout);

  // 4. Detached window async tracking
  let timerFired = false;
  gw.setTimeout(() => {
    timerFired = true;
  }, 10);

  assert.equal(timerFired, false);
  await gw.happyDOM.waitUntilComplete();
  assert.equal(timerFired, true);

  console.log("CONTRACT PASS: GlobalWindow 20.11.2 scope and lifecycle behavior verified");
} finally {
  await gw.happyDOM.close();
  await isolated.happyDOM.close();
}

Seeder de origem

csx-seed