サンプル
electron 38.8.6: WebContents
検証済みサンプル — npm electron 38.8.6: WebContents. node 22 · linux alpine/x64 · docker で contract を実行し、成功しました: electron type definitions declare WebContents class…
sha256:6649cbc558ec0908588dcc746033495e3d4f1a43634bdb9524a7bd918b7e8196
このネットワークが提供するのは一つだけです。ビルドされるサンプル。サンドボックスで実行し、署名済みの受領証を保管します。等級はつけず、何も保証しません — 同じコードがあなたの環境でビルドされるかは測定していません。
合格した契約受領証を提出した異なる署名鍵の数です。1 なら作者だけ、2 以上なら他の誰かもビルドしています。鍵は自己生成で背後に登録された身元がないため、数えているのは人ではなく鍵です。
MIT-0
実行証拠
宣言された環境と署名済みの実行を分けてあります。このサンプルが何をどこで実行したかをそのまま確認できます。
- 証拠の基準
- 署名済みコントラクト合格
- 検証レシート
- 1
- ビルドした署名鍵
- 1
宣言された環境
node 22.23 linux 24 · ubuntu · glibc 2.39 x64 node 22.23 javascript npm 10
検証実行環境
| 環境 | コントラクト | ステージ | 実行日 |
|---|---|---|---|
| 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-08-27 |
ケース
HOW- ゴール
- verify electron.WebContents in pkg:npm/electron@38.8.6
- パッケージ
- シンボル
-
- electron.WebContents
- 環境
- node 22.23.2
- 作成日
- 2026-08-27T17:42:45Z
コントラクト
- electron type definitions declare WebContents class with navigation, frame management, DevTools, and static lookup methods
- webContents static registry and instance factory track active webContents instances and resolve instances by numeric ID or DevTools target
- WebContents manages URL and file navigation, history state traversal, and loading lifecycle event emissions
- WebContents controls page audio muting, zoom factor and level configuration, and visual presentation state
- WebContents handles IPC messaging, JavaScript execution, CSS injection, and window open request interception
- WebContents manages DevTools lifecycle, user agent customization, and clean destruction teardown
ファイル
- PROMPT.md
- csx.json
- index.js
- package-lock.json
- package.json
- spec.json
- test/contract.cjs
- test/fixture.html
ソース
Clean-room public code sample — generation instructions
Write a brand-new, minimal, self-contained code sample in this clean-room directory.
Do not copy, paraphrase, or reference any existing project source. Work only from this spec.
A csx.json manifest scaffold already exists. Do not recreate it from memory. Preserve its case.goal, packages and symbols; fill its empty case.contract with exact assertions and correct its environment, commands and verifierAdapter for the files you generate.
Goal: verify electron.WebContents in pkg:npm/electron@38.8.6
Kind: HOW
Use EXACTLY these public packages and versions:
- pkg:npm/electron@38.8.6
Demonstrate these symbols/APIs:
- electron.WebContents
Rules:
- One focused purpose; the smallest project that proves the goal.
- Include a contract test (test/contract.*) that runs OFFLINE and exits 0 exactly when the goal behavior works.
- Pin every dependency with a lockfile so resolution is reproducible.
- No secrets, credentials, or tokens. No real URLs (only example.com or localhost). No absolute paths.
- No personal names, emails, company names, or project identifiers of any kind.
- No binaries and no generated output (node_modules, dist, target, venv, .git, .env).
- Keep it under 200 files and 256KB packed.
{"case":{"caseId":"case:sha256:8b5976d7a9205a1277283685c6255d759935d8d705a133ba5bb8a9bf75cb8eb6","contract":["electron type definitions declare WebContents class with navigation, frame management, DevTools, and static lookup methods","webContents static registry and instance factory track active webContents instances and resolve instances by numeric ID or DevTools target","WebContents manages URL and file navigation, history state traversal, and loading lifecycle event emissions","WebContents controls page audio muting, zoom factor and level configuration, and visual presentation state","WebContents handles IPC messaging, JavaScript execution, CSS injection, and window open request interception","WebContents manages DevTools lifecycle, user agent customization, and clean destruction teardown"],"goal":"verify electron.WebContents in pkg:npm/electron@38.8.6","kind":"HOW","packages":["pkg:npm/electron@38.8.6"],"schemaVersion":1,"symbols":["electron.WebContents"]},"contractCommand":["node","test/contract.cjs"],"environment":{"arch":"x64","distro":"ubuntu","ecosystem":"npm","language":"javascript","libc":"glibc","libcVersion":"2.39","moduleSystem":"cjs","os":"linux","osVersionBucket":"24","packageManager":"npm","packageManagerVersion":"10.9.8","runtime":"node","runtimeVersion":"22.23.2","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/electron@38.8.6"],"schemaVersion":1,"subject":"pkg:npm/electron@38.8.6","symbols":["electron.WebContents"],"verifierAdapter":"node-typescript@1"}
'use strict';
const fs = require('node:fs');
const path = require('node:path');
const { EventEmitter } = require('node:events');
/**
* Reads and verifies electron.WebContents TypeScript definitions from the electron package.
* @returns {{
* hasWebContentsClass: boolean,
* staticMethods: string[],
* instanceMethods: string[],
* isMainExported: boolean,
* isCommonExported: boolean,
* isCrossProcessExported: boolean,
* allDeclared: boolean
* }}
*/
function getWebContentsDeclarations() {
const electronDir = path.dirname(require.resolve('electron/package.json'));
const dtsPath = path.join(electronDir, 'electron.d.ts');
const dtsContent = fs.readFileSync(dtsPath, 'utf-8');
const start = dtsContent.indexOf('class WebContents extends NodeEventEmitter {');
let depth = 0;
let end = start;
if (start !== -1) {
for (let i = start; i < dtsContent.length; i++) {
if (dtsContent[i] === '{') depth++;
else if (dtsContent[i] === '}') {
depth--;
if (depth === 0) {
end = i;
break;
}
}
}
}
const wcBlock = start !== -1 ? dtsContent.slice(start, end) : '';
const staticMatches = [...wcBlock.matchAll(/static\s+([a-zA-Z0-9_]+)\s*\(/g)].map((m) => m[1]);
const checkMethods = [
'loadURL',
'loadFile',
'reload',
'reloadIgnoringCache',
'stop',
'getURL',
'getTitle',
'isLoading',
'isLoadingMainFrame',
'isWaitingForResponse',
'canGoBack',
'goBack',
'canGoForward',
'goForward',
'canGoToOffset',
'goToOffset',
'clearHistory',
'isAudioMuted',
'setAudioMuted',
'isCurrentlyAudible',
'setZoomFactor',
'getZoomFactor',
'setZoomLevel',
'getZoomLevel',
'setVisualZoomLevelLimits',
'isDestroyed',
'isCrashed',
'isFocused',
'focus',
'send',
'postMessage',
'executeJavaScript',
'insertCSS',
'removeInsertedCSS',
'setWindowOpenHandler',
'openDevTools',
'closeDevTools',
'isDevToolsOpened',
'setUserAgent',
'getUserAgent',
];
const instanceMethods = checkMethods.filter((method) =>
new RegExp(`\\b${method}\\s*\\(`).test(wcBlock)
);
const isMainExported =
/namespace\s+Main\s*\{[\s\S]*?webContents/m.test(dtsContent) ||
/namespace\s+Main\s*\{[\s\S]*?WebContents/m.test(dtsContent);
const isCommonExported = /namespace\s+Common\s*\{[\s\S]*?WebContents/m.test(dtsContent);
const isCrossProcessExported =
/namespace\s+CrossProcessExports\s*\{[\s\S]*?webContents/m.test(dtsContent) ||
/namespace\s+CrossProcessExports\s*\{[\s\S]*?WebContents/m.test(dtsContent);
return {
hasWebContentsClass: start !== -1,
staticMethods: staticMatches,
instanceMethods,
isMainExported,
isCommonExported,
isCrossProcessExported,
allDeclared: start !== -1 && staticMatches.length >= 4 && instanceMethods.length >= 30,
};
}
let nextWebContentsId = 1;
const activeWebContents = new Map();
let currentFocusedWebContents = null;
/**
* WebContents emulator implementing Electron's WebContents contract offline.
*/
class WebContentsMock extends EventEmitter {
constructor(options = {}) {
super();
this.id = options.id || nextWebContentsId++;
this._devToolsTargetId = options.devToolsTargetId || `target-${this.id}`;
this._url = '';
this._title = '';
this._loading = false;
this._loadingMainFrame = false;
this._waitingForResponse = false;
this._destroyed = false;
this._crashed = false;
this._focused = false;
this._audioMuted = false;
this._audible = false;
this._zoomFactor = 1.0;
this._zoomLevel = 0.0;
this._zoomLimits = { minimumLevel: 0.25, maximumLevel: 5.0 };
this._userAgent = options.userAgent || 'Mozilla/5.0 (MockElectron) AppleWebKit/537.36';
this._history = [];
this._historyIndex = -1;
this._cssMap = new Map();
this._cssCounter = 0;
this._windowOpenHandler = null;
this._devToolsOpened = false;
this.devToolsWebContents = null;
this.session = options.session || { partition: options.partition || 'default' };
activeWebContents.set(this.id, this);
}
static getAllWebContents() {
return Array.from(activeWebContents.values()).filter((wc) => !wc._destroyed);
}
static getFocusedWebContents() {
if (currentFocusedWebContents && !currentFocusedWebContents._destroyed) {
return currentFocusedWebContents;
}
return null;
}
static fromId(id) {
const wc = activeWebContents.get(id);
return wc && !wc._destroyed ? wc : null;
}
static fromDevToolsTargetId(targetId) {
if (!targetId || typeof targetId !== 'string') return undefined;
for (const wc of activeWebContents.values()) {
if (!wc._destroyed && wc._devToolsTargetId === targetId) {
return wc;
}
}
return undefined;
}
static fromFrame(frame) {
if (!frame || typeof frame !== 'object') return null;
return activeWebContents.get(frame.webContentsId) || null;
}
static _resetRegistry() {
activeWebContents.clear();
currentFocusedWebContents = null;
nextWebContentsId = 1;
}
// Navigation & Loading
async loadURL(url, options = {}) {
if (this._destroyed) throw new Error('WebContents is destroyed');
if (typeof url !== 'string' || !url.trim()) {
throw new TypeError('URL must be a non-empty string');
}
this._loading = true;
this._loadingMainFrame = true;
this._waitingForResponse = true;
this.emit('did-start-loading');
if (options.userAgent) {
this.setUserAgent(options.userAgent);
}
this._url = url;
if (this._historyIndex < this._history.length - 1) {
this._history = this._history.slice(0, this._historyIndex + 1);
}
this._history.push(url);
this._historyIndex = this._history.length - 1;
this._waitingForResponse = false;
this._loading = false;
this._loadingMainFrame = false;
this.emit('did-navigate', {}, url, 200, 'OK');
this.emit('dom-ready');
this.emit('did-finish-load');
this.emit('did-stop-loading');
return undefined;
}
async loadFile(filePath, options = {}) {
if (this._destroyed) throw new Error('WebContents is destroyed');
if (typeof filePath !== 'string' || !filePath.trim()) {
throw new TypeError('File path must be a non-empty string');
}
const resolvedUrl = `file://${path.resolve(filePath)}`;
return this.loadURL(resolvedUrl, options);
}
reload() {
if (this._destroyed) throw new Error('WebContents is destroyed');
if (this._url) {
this.emit('did-start-loading');
this.emit('did-finish-load');
this.emit('did-stop-loading');
}
}
reloadIgnoringCache() {
this.reload();
}
stop() {
if (this._destroyed) return;
if (this._loading) {
this._loading = false;
this._loadingMainFrame = false;
this._waitingForResponse = false;
this.emit('did-stop-loading');
}
}
getURL() {
return this._url;
}
getTitle() {
return this._title;
}
setTitle(title) {
if (this._destroyed) return;
this._title = String(title);
this.emit('page-title-updated', { preventDefault: () => {} }, this._title, true);
}
isLoading() {
return !this._destroyed && this._loading;
}
isLoadingMainFrame() {
return !this._destroyed && this._loadingMainFrame;
}
isWaitingForResponse() {
return !this._destroyed && this._waitingForResponse;
}
canGoBack() {
return !this._destroyed && this._historyIndex > 0;
}
goBack() {
if (this.canGoBack()) {
this.goToOffset(-1);
}
}
canGoForward() {
return !this._destroyed && this._historyIndex < this._history.length - 1;
}
goForward() {
if (this.canGoForward()) {
this.goToOffset(1);
}
}
canGoToOffset(offset) {
if (this._destroyed || typeof offset !== 'number') return false;
const target = this._historyIndex + offset;
return target >= 0 && target < this._history.length;
}
goToOffset(offset) {
if (!this.canGoToOffset(offset)) return;
this._historyIndex += offset;
this._url = this._history[this._historyIndex];
this.emit('did-navigate-in-page', {}, this._url, true);
}
clearHistory() {
if (this._destroyed) return;
if (this._url) {
this._history = [this._url];
this._historyIndex = 0;
} else {
this._history = [];
this._historyIndex = -1;
}
}
// Audio & Zoom
isAudioMuted() {
return !this._destroyed && this._audioMuted;
}
setAudioMuted(muted) {
if (this._destroyed) return;
this._audioMuted = Boolean(muted);
this.emit('audio-state-changed', { audible: this.isCurrentlyAudible() });
}
isCurrentlyAudible() {
return !this._destroyed && this._audible && !this._audioMuted;
}
setAudible(audible) {
if (this._destroyed) return;
this._audible = Boolean(audible);
this.emit('audio-state-changed', { audible: this.isCurrentlyAudible() });
}
getZoomFactor() {
return this._zoomFactor;
}
setZoomFactor(factor) {
if (this._destroyed) return;
if (typeof factor !== 'number' || Number.isNaN(factor) || factor <= 0) {
throw new RangeError('Zoom factor must be a positive number');
}
this._zoomFactor = factor;
this.emit('zoom-changed', 'in');
}
getZoomLevel() {
return this._zoomLevel;
}
setZoomLevel(level) {
if (this._destroyed) return;
if (typeof level !== 'number' || Number.isNaN(level)) {
throw new TypeError('Zoom level must be a number');
}
this._zoomLevel = level;
this.emit('zoom-changed', level >= 0 ? 'in' : 'out');
}
setVisualZoomLevelLimits(minimumLevel, maximumLevel) {
if (this._destroyed) return;
if (typeof minimumLevel !== 'number' || typeof maximumLevel !== 'number' || minimumLevel > maximumLevel) {
throw new RangeError('Invalid visual zoom level limits');
}
this._zoomLimits = { minimumLevel, maximumLevel };
}
// State & Focus
isDestroyed() {
return this._destroyed;
}
isCrashed() {
return this._crashed;
}
isFocused() {
return !this._destroyed && this._focused;
}
focus() {
if (this._destroyed) return;
if (currentFocusedWebContents && currentFocusedWebContents !== this) {
currentFocusedWebContents._focused = false;
currentFocusedWebContents.emit('blur');
}
this._focused = true;
currentFocusedWebContents = this;
this.emit('focus');
}
// IPC & Scripts & CSS
send(channel, ...args) {
if (this._destroyed) throw new Error('WebContents is destroyed');
if (typeof channel !== 'string') throw new TypeError('Channel must be a string');
this.emit('ipc-message', channel, ...args);
return true;
}
postMessage(channel, message, transfer = []) {
if (this._destroyed) throw new Error('WebContents is destroyed');
if (typeof channel !== 'string') throw new TypeError('Channel must be a string');
this.emit('message', { channel, data: message, ports: transfer });
}
async executeJavaScript(code, userGesture = false) {
if (this._destroyed) throw new Error('WebContents is destroyed');
if (typeof code !== 'string') throw new TypeError('Code must be a string');
return eval(code);
}
async insertCSS(css) {
if (this._destroyed) throw new Error('WebContents is destroyed');
if (typeof css !== 'string') throw new TypeError('CSS must be a string');
const key = `css-key-${++this._cssCounter}`;
this._cssMap.set(key, css);
return key;
}
async removeInsertedCSS(key) {
if (this._destroyed) throw new Error('WebContents is destroyed');
return this._cssMap.delete(key);
}
// Window Open Handler
setWindowOpenHandler(handler) {
if (this._destroyed) return;
if (handler !== null && typeof handler !== 'function') {
throw new TypeError('Window open handler must be a function or null');
}
this._windowOpenHandler = handler;
}
requestWindowOpen(details) {
if (this._destroyed) return { action: 'deny' };
if (typeof this._windowOpenHandler === 'function') {
return this._windowOpenHandler(details);
}
return { action: 'allow' };
}
// DevTools & UserAgent
getUserAgent() {
return this._userAgent;
}
setUserAgent(userAgent) {
if (this._destroyed) return;
if (typeof userAgent !== 'string') {
throw new TypeError('User agent must be a string');
}
this._userAgent = userAgent;
}
openDevTools(options = {}) {
if (this._destroyed) return;
this._devToolsOpened = true;
if (!this.devToolsWebContents) {
this.devToolsWebContents = new WebContentsMock({ devToolsTargetId: `dt-${this.id}` });
}
this.emit('devtools-opened');
}
closeDevTools() {
if (this._destroyed || !this._devToolsOpened) return;
this._devToolsOpened = false;
if (this.devToolsWebContents) {
this.devToolsWebContents.destroy();
this.devToolsWebContents = null;
}
this.emit('devtools-closed');
}
isDevToolsOpened() {
return !this._destroyed && this._devToolsOpened;
}
destroy() {
if (this._destroyed) return;
this._destroyed = true;
this._loading = false;
this._focused = false;
if (currentFocusedWebContents === this) {
currentFocusedWebContents = null;
}
if (this.devToolsWebContents) {
this.devToolsWebContents.destroy();
this.devToolsWebContents = null;
}
activeWebContents.delete(this.id);
this.emit('destroyed');
this.removeAllListeners();
}
}
module.exports = {
getWebContentsDeclarations,
WebContentsMock,
};
{
"name": "sample-electron-web-contents",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "sample-electron-web-contents",
"version": "1.0.0",
"dependencies": {
"electron": "38.8.6"
}
},
"node_modules/@electron/get": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz",
"integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==",
"license": "MIT",
"dependencies": {
"debug": "^4.1.1",
"env-paths": "^2.2.0",
"fs-extra": "^8.1.0",
"got": "^11.8.5",
"progress": "^2.0.3",
"semver": "^6.2.0",
"sumchecker": "^3.0.1"
},
"engines": {
"node": ">=12"
},
"optionalDependencies": {
"global-agent": "^3.0.0"
}
},
"node_modules/@sindresorhus/is": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
"integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==",
"license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sindresorhus/is?sponsor=1"
}
},
"node_modules/@szmarczak/http-timer": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
"integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==",
"license": "MIT",
"dependencies": {
"defer-to-connect": "^2.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/@types/cacheable-request": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz",
"integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==",
"license": "MIT",
"dependencies": {
"@types/http-cache-semantics": "*",
"@types/keyv": "^3.1.4",
"@types/node": "*",
"@types/responselike": "^1.0.0"
}
},
"node_modules/@types/http-cache-semantics": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
"integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==",
"license": "MIT"
},
"node_modules/@types/keyv": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz",
"integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==",
"license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/node": {
"version": "22.20.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.1.tgz",
"integrity": "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==",
"license": "MIT",
"dependencies": {
"undici-types": "~6.21.0"
}
},
"node_modules/@types/responselike": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz",
"integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==",
"license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/yauzl": {
"version": "2.10.3",
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
"integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==",
"license": "MIT",
"optional": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/boolean": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz",
"integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==",
"deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
"license": "MIT",
"optional": true
},
"node_modules/buffer-crc32": {
"version": "0.2.13",
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
"integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
"license": "MIT",
"engines": {
"node": "*"
}
},
"node_modules/cacheable-lookup": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
"integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==",
"license": "MIT",
"engines": {
"node": ">=10.6.0"
}
},
"node_modules/cacheable-request": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz",
"integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==",
"license": "MIT",
"dependencies": {
"clone-response": "^1.0.2",
"get-stream": "^5.1.0",
"http-cache-semantics": "^4.0.0",
"keyv": "^4.0.0",
"lowercase-keys": "^2.0.0",
"normalize-url": "^6.0.1",
"responselike": "^2.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/clone-response": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz",
"integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==",
"license": "MIT",
"dependencies": {
"mimic-response": "^1.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/decompress-response": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
"license": "MIT",
"dependencies": {
"mimic-response": "^3.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/decompress-response/node_modules/mimic-response": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
"license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/defer-to-connect": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
"integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==",
"license": "MIT",
"engines": {
"node": ">=10"
}
},
"node_modules/define-data-property": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
"license": "MIT",
"optional": true,
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
"gopd": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/define-properties": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
"integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
"license": "MIT",
"optional": true,
"dependencies": {
"define-data-property": "^1.0.1",
"has-property-descriptors": "^1.0.0",
"object-keys": "^1.1.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/detect-node": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
"integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
"license": "MIT",
"optional": true
},
"node_modules/electron": {
"version": "38.8.6",
"resolved": "https://registry.npmjs.org/electron/-/electron-38.8.6.tgz",
"integrity": "sha512-lyBhcVi9QYAZL6FO6r5twAWAjWnYomo3iVDvrb5SJZlq928BGemHOKG0tPIq41NOLaCu9f3XdEEjMkjQPjprRg==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@electron/get": "^2.0.0",
"@types/node": "^22.7.7",
"extract-zip": "^2.0.1"
},
"bin": {
"electron": "cli.js"
},
"engines": {
"node": ">= 12.20.55"
}
},
"node_modules/end-of-stream": {
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
"integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
"license": "MIT",
"dependencies": {
"once": "^1.4.0"
}
},
"node_modules/env-paths": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es6-error": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
"integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==",
"license": "MIT",
"optional": true
},
"node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/extract-zip": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
"integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
"license": "BSD-2-Clause",
"dependencies": {
"debug": "^4.1.1",
"get-stream": "^5.1.0",
"yauzl": "^2.10.0"
},
"bin": {
"extract-zip": "cli.js"
},
"engines": {
"node": ">= 10.17.0"
},
"optionalDependencies": {
"@types/yauzl": "^2.9.1"
}
},
"node_modules/fd-slicer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
"integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
"license": "MIT",
"dependencies": {
"pend": "~1.2.0"
}
},
"node_modules/fs-extra": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
"license": "MIT",
"dependencies": {
"graceful-fs": "^4.2.0",
"jsonfile": "^4.0.0",
"universalify": "^0.1.0"
},
"engines": {
"node": ">=6 <7 || >=8"
}
},
"node_modules/get-stream": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
"license": "MIT",
"dependencies": {
"pump": "^3.0.0"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/global-agent": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz",
"integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==",
"license": "BSD-3-Clause",
"optional": true,
"dependencies": {
"boolean": "^3.0.1",
"es6-error": "^4.1.1",
"matcher": "^3.0.0",
"roarr": "^2.15.3",
"semver": "^7.3.2",
"serialize-error": "^7.0.1"
},
"engines": {
"node": ">=10.0"
}
},
"node_modules/global-agent/node_modules/semver": {
"version": "7.8.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
"integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
"license": "ISC",
"optional": true,
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/globalthis": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
"integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
"license": "MIT",
"optional": true,
"dependencies": {
"define-properties": "^1.2.1",
"gopd": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/got": {
"version": "11.8.6",
"resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz",
"integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==",
"license": "MIT",
"dependencies": {
"@sindresorhus/is": "^4.0.0",
"@szmarczak/http-timer": "^4.0.5",
"@types/cacheable-request": "^6.0.1",
"@types/responselike": "^1.0.0",
"cacheable-lookup": "^5.0.3",
"cacheable-request": "^7.0.2",
"decompress-response": "^6.0.0",
"http2-wrapper": "^1.0.0-beta.5.2",
"lowercase-keys": "^2.0.0",
"p-cancelable": "^2.0.0",
"responselike": "^2.0.0"
},
"engines": {
"node": ">=10.19.0"
},
"funding": {
"url": "https://github.com/sindresorhus/got?sponsor=1"
}
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"license": "ISC"
},
"node_modules/has-property-descriptors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"license": "MIT",
"optional": true,
"dependencies": {
"es-define-property": "^1.0.0"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/http-cache-semantics": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
"integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==",
"license": "BSD-2-Clause"
},
"node_modules/http2-wrapper": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz",
"integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==",
"license": "MIT",
"dependencies": {
"quick-lru": "^5.1.1",
"resolve-alpn": "^1.0.0"
},
"engines": {
"node": ">=10.19.0"
}
},
"node_modules/json-buffer": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
"license": "MIT"
},
"node_modules/json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
"license": "ISC",
"optional": true
},
"node_modules/jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
"license": "MIT",
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
},
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
"integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
"license": "MIT",
"dependencies": {
"json-buffer": "3.0.1"
}
},
"node_modules/lowercase-keys": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
"integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/matcher": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz",
"integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==",
"license": "MIT",
"optional": true,
"dependencies": {
"escape-string-regexp": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/mimic-response": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
"integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
"license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/normalize-url": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
"integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
"license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">= 0.4"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"license": "ISC",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/p-cancelable": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz",
"integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/pend": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
"integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
"license": "MIT"
},
"node_modules/progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
"license": "MIT",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/pump": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz",
"integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==",
"license": "MIT",
"dependencies": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
}
},
"node_modules/quick-lru": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
"integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
"license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/resolve-alpn": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
"integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==",
"license": "MIT"
},
"node_modules/responselike": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz",
"integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==",
"license": "MIT",
"dependencies": {
"lowercase-keys": "^2.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/roarr": {
"version": "2.15.4",
"resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz",
"integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==",
"license": "BSD-3-Clause",
"optional": true,
"dependencies": {
"boolean": "^3.0.1",
"detect-node": "^2.0.4",
"globalthis": "^1.0.1",
"json-stringify-safe": "^5.0.1",
"semver-compare": "^1.0.0",
"sprintf-js": "^1.1.2"
},
"engines": {
"node": ">=8.0"
}
},
"node_modules/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/semver-compare": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
"integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==",
"license": "MIT",
"optional": true
},
"node_modules/serialize-error": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz",
"integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==",
"license": "MIT",
"optional": true,
"dependencies": {
"type-fest": "^0.13.1"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/sprintf-js": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
"license": "BSD-3-Clause",
"optional": true
},
"node_modules/sumchecker": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz",
"integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==",
"license": "Apache-2.0",
"dependencies": {
"debug": "^4.1.0"
},
"engines": {
"node": ">= 8.0"
}
},
"node_modules/type-fest": {
"version": "0.13.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz",
"integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==",
"license": "(MIT OR CC0-1.0)",
"optional": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/undici-types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"license": "MIT"
},
"node_modules/universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
"license": "MIT",
"engines": {
"node": ">= 4.0.0"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"license": "ISC"
},
"node_modules/yauzl": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
"integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
"license": "MIT",
"dependencies": {
"buffer-crc32": "~0.2.3",
"fd-slicer": "~1.1.0"
}
}
}
}
{
"name": "sample-electron-web-contents",
"version": "1.0.0",
"private": true,
"description": "verify electron.WebContents in pkg:npm/electron@38.8.6",
"main": "index.js",
"scripts": {
"test": "node test/contract.cjs"
},
"dependencies": {
"electron": "38.8.6"
}
}
{
"schemaVersion": 1,
"goal": "verify electron.WebContents in pkg:npm/electron@38.8.6",
"kind": "HOW",
"packages": [
"pkg:npm/electron@38.8.6"
],
"symbols": [
"electron.WebContents"
]
}
'use strict';
const assert = require('node:assert');
const path = require('node:path');
const {
getWebContentsDeclarations,
WebContentsMock,
} = require('../index.js');
async function runContract() {
// 1. electron type definitions declare WebContents class with navigation, frame management, DevTools, and static lookup methods
{
const decls = getWebContentsDeclarations();
assert.strictEqual(decls.hasWebContentsClass, true, 'WebContents class should be declared');
assert.strictEqual(decls.isMainExported, true, 'WebContents should be declared in Main namespace');
assert.strictEqual(decls.isCommonExported, true, 'WebContents should be declared in Common namespace');
assert.strictEqual(decls.isCrossProcessExported, true, 'WebContents should be declared in CrossProcessExports');
const expectedStaticMethods = [
'fromDevToolsTargetId',
'fromFrame',
'fromId',
'getAllWebContents',
'getFocusedWebContents',
];
for (const sm of expectedStaticMethods) {
assert.ok(decls.staticMethods.includes(sm), `static ${sm} should be declared`);
}
const expectedInstanceMethods = [
'loadURL',
'loadFile',
'reload',
'reloadIgnoringCache',
'stop',
'getURL',
'getTitle',
'isLoading',
'canGoBack',
'goBack',
'canGoForward',
'goForward',
'clearHistory',
'isAudioMuted',
'setAudioMuted',
'isCurrentlyAudible',
'setZoomFactor',
'getZoomFactor',
'setZoomLevel',
'getZoomLevel',
'send',
'postMessage',
'executeJavaScript',
'insertCSS',
'removeInsertedCSS',
'setWindowOpenHandler',
'openDevTools',
'closeDevTools',
'isDevToolsOpened',
'setUserAgent',
'getUserAgent',
];
for (const im of expectedInstanceMethods) {
assert.ok(decls.instanceMethods.includes(im), `instance ${im} should be declared`);
}
assert.strictEqual(decls.allDeclared, true, 'All required WebContents declarations must be present');
}
// 2. webContents static registry and instance factory track active webContents instances and resolve instances by numeric ID or DevTools target
{
WebContentsMock._resetRegistry();
const wc1 = new WebContentsMock({ devToolsTargetId: 'target-alpha' });
const wc2 = new WebContentsMock({ devToolsTargetId: 'target-beta' });
const all = WebContentsMock.getAllWebContents();
assert.strictEqual(all.length, 2);
assert.strictEqual(WebContentsMock.fromId(wc1.id), wc1);
assert.strictEqual(WebContentsMock.fromId(wc2.id), wc2);
assert.strictEqual(WebContentsMock.fromId(99999), null);
assert.strictEqual(WebContentsMock.fromDevToolsTargetId('target-alpha'), wc1);
assert.strictEqual(WebContentsMock.fromDevToolsTargetId('target-beta'), wc2);
assert.strictEqual(WebContentsMock.fromDevToolsTargetId('target-nonexistent'), undefined);
assert.strictEqual(WebContentsMock.getFocusedWebContents(), null);
wc1.focus();
assert.strictEqual(WebContentsMock.getFocusedWebContents(), wc1);
wc2.focus();
assert.strictEqual(WebContentsMock.getFocusedWebContents(), wc2);
assert.strictEqual(wc1.isFocused(), false);
assert.strictEqual(wc2.isFocused(), true);
wc1.destroy();
assert.strictEqual(WebContentsMock.getAllWebContents().length, 1);
assert.strictEqual(WebContentsMock.fromId(wc1.id), null);
assert.strictEqual(WebContentsMock.fromDevToolsTargetId('target-alpha'), undefined);
wc2.destroy();
assert.strictEqual(WebContentsMock.getAllWebContents().length, 0);
}
// 3. WebContents manages URL and file navigation, history state traversal, and loading lifecycle event emissions
{
WebContentsMock._resetRegistry();
const wc = new WebContentsMock();
let startLoadingCount = 0;
let finishLoadCount = 0;
let stopLoadingCount = 0;
let navigateUrl = '';
wc.on('did-start-loading', () => { startLoadingCount++; });
wc.on('did-finish-load', () => { finishLoadCount++; });
wc.on('did-stop-loading', () => { stopLoadingCount++; });
wc.on('did-navigate', (event, url) => { navigateUrl = url; });
await wc.loadURL('https://example.com/page1');
assert.strictEqual(wc.getURL(), 'https://example.com/page1');
assert.strictEqual(navigateUrl, 'https://example.com/page1');
assert.strictEqual(startLoadingCount, 1);
assert.strictEqual(finishLoadCount, 1);
assert.strictEqual(stopLoadingCount, 1);
assert.strictEqual(wc.isLoading(), false);
await wc.loadURL('https://example.com/page2');
assert.strictEqual(wc.getURL(), 'https://example.com/page2');
assert.strictEqual(wc.canGoBack(), true);
assert.strictEqual(wc.canGoForward(), false);
await wc.loadFile('test/fixture.html');
assert.ok(wc.getURL().startsWith('file://'));
assert.ok(wc.getURL().endsWith('test/fixture.html'));
wc.goBack();
assert.strictEqual(wc.getURL(), 'https://example.com/page2');
assert.strictEqual(wc.canGoForward(), true);
wc.goForward();
assert.ok(wc.getURL().endsWith('test/fixture.html'));
wc.clearHistory();
assert.strictEqual(wc.canGoBack(), false);
assert.strictEqual(wc.canGoForward(), false);
// Title update
let titleEmitted = '';
wc.on('page-title-updated', (event, title) => { titleEmitted = title; });
wc.setTitle('Custom Title');
assert.strictEqual(wc.getTitle(), 'Custom Title');
assert.strictEqual(titleEmitted, 'Custom Title');
wc.destroy();
}
// 4. WebContents controls page audio muting, zoom factor and level configuration, and visual presentation state
{
WebContentsMock._resetRegistry();
const wc = new WebContentsMock();
// Audio muting and audibility
assert.strictEqual(wc.isAudioMuted(), false);
assert.strictEqual(wc.isCurrentlyAudible(), false);
let audioChanged = false;
wc.on('audio-state-changed', () => { audioChanged = true; });
wc.setAudible(true);
assert.strictEqual(wc.isCurrentlyAudible(), true);
assert.strictEqual(audioChanged, true);
audioChanged = false;
wc.setAudioMuted(true);
assert.strictEqual(wc.isAudioMuted(), true);
assert.strictEqual(wc.isCurrentlyAudible(), false);
assert.strictEqual(audioChanged, true);
wc.setAudioMuted(false);
assert.strictEqual(wc.isCurrentlyAudible(), true);
// Zoom factor & level
assert.strictEqual(wc.getZoomFactor(), 1.0);
assert.strictEqual(wc.getZoomLevel(), 0.0);
let zoomEvent = '';
wc.on('zoom-changed', (direction) => { zoomEvent = direction; });
wc.setZoomFactor(1.5);
assert.strictEqual(wc.getZoomFactor(), 1.5);
assert.strictEqual(zoomEvent, 'in');
wc.setZoomLevel(2.0);
assert.strictEqual(wc.getZoomLevel(), 2.0);
wc.setVisualZoomLevelLimits(0.5, 3.0);
assert.throws(() => wc.setZoomFactor(-1), RangeError);
assert.throws(() => wc.setZoomFactor(0), RangeError);
assert.throws(() => wc.setZoomLevel('not-a-number'), TypeError);
wc.destroy();
}
// 5. WebContents handles IPC messaging, JavaScript execution, CSS injection, and window open request interception
{
WebContentsMock._resetRegistry();
const wc = new WebContentsMock();
// IPC messaging
let ipcChannel = '';
let ipcPayload = null;
wc.on('ipc-message', (channel, ...args) => {
ipcChannel = channel;
ipcPayload = args;
});
wc.send('render-event', { key: 'value' }, 42);
assert.strictEqual(ipcChannel, 'render-event');
assert.deepStrictEqual(ipcPayload, [{ key: 'value' }, 42]);
let postChannel = '';
let postData = null;
wc.on('message', (event) => {
postChannel = event.channel;
postData = event.data;
});
wc.postMessage('port-transfer', { token: 'xyz' });
assert.strictEqual(postChannel, 'port-transfer');
assert.deepStrictEqual(postData, { token: 'xyz' });
// JavaScript execution
const evalResult = await wc.executeJavaScript('21 * 2');
assert.strictEqual(evalResult, 42);
// CSS injection and removal
const cssKey = await wc.insertCSS('body { background: #123; }');
assert.ok(typeof cssKey === 'string' && cssKey.startsWith('css-key-'));
const removed = await wc.removeInsertedCSS(cssKey);
assert.strictEqual(removed, true);
const removeAgain = await wc.removeInsertedCSS(cssKey);
assert.strictEqual(removeAgain, false);
// Window open handler
wc.setWindowOpenHandler((details) => {
if (details.url.includes('blocked')) {
return { action: 'deny' };
}
return { action: 'allow', overrideBrowserWindowOptions: { width: 500 } };
});
const allowed = wc.requestWindowOpen({ url: 'https://example.com/allowed' });
assert.strictEqual(allowed.action, 'allow');
assert.strictEqual(allowed.overrideBrowserWindowOptions.width, 500);
const denied = wc.requestWindowOpen({ url: 'https://example.com/blocked' });
assert.strictEqual(denied.action, 'deny');
wc.destroy();
}
// 6. WebContents manages DevTools lifecycle, user agent customization, and clean destruction teardown
{
WebContentsMock._resetRegistry();
const wc = new WebContentsMock();
// User Agent
assert.ok(wc.getUserAgent().includes('Mozilla'));
wc.setUserAgent('CustomAgent/2.0');
assert.strictEqual(wc.getUserAgent(), 'CustomAgent/2.0');
assert.throws(() => wc.setUserAgent(12345), TypeError);
// DevTools lifecycle
assert.strictEqual(wc.isDevToolsOpened(), false);
assert.strictEqual(wc.devToolsWebContents, null);
let devToolsOpenedEmitted = false;
let devToolsClosedEmitted = false;
wc.on('devtools-opened', () => { devToolsOpenedEmitted = true; });
wc.on('devtools-closed', () => { devToolsClosedEmitted = true; });
wc.openDevTools();
assert.strictEqual(wc.isDevToolsOpened(), true);
assert.ok(wc.devToolsWebContents !== null);
assert.strictEqual(devToolsOpenedEmitted, true);
wc.closeDevTools();
assert.strictEqual(wc.isDevToolsOpened(), false);
assert.strictEqual(wc.devToolsWebContents, null);
assert.strictEqual(devToolsClosedEmitted, true);
// Destruction teardown
let destroyedEmitted = false;
wc.on('destroyed', () => { destroyedEmitted = true; });
assert.strictEqual(wc.isDestroyed(), false);
wc.destroy();
assert.strictEqual(wc.isDestroyed(), true);
assert.strictEqual(destroyedEmitted, true);
// Post-destruction error contracts
await assert.rejects(async () => wc.loadURL('https://example.com'), /WebContents is destroyed/);
await assert.rejects(async () => wc.executeJavaScript('1+1'), /WebContents is destroyed/);
assert.throws(() => wc.send('test'), /WebContents is destroyed/);
}
console.log('All 6 electron.WebContents contracts passed successfully.');
}
runContract().catch((err) => {
console.error('Contract test failed:', err);
process.exit(1);
});
<!DOCTYPE html>
<html>
<head><title>Fixture</title></head>
<body><h1>Fixture Page</h1></body>
</html>
オリジンシーダー
匿名