• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

electron / fiddle / 13755753799

10 Mar 2025 02:47AM UTC coverage: 87.472%. Remained the same
13755753799

Pull #1689

github

web-flow
Merge 2a6771c28 into 72117c806
Pull Request #1689: build(deps): bump dsanders11/project-actions from 1.5.2 to 1.7.0

983 of 1223 branches covered (80.38%)

Branch coverage included in aggregate %.

3772 of 4213 relevant lines covered (89.53%)

34.68 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

50.55
/src/main/fiddle-core.ts
1
import { ChildProcess } from 'node:child_process';
2

3
import { ElectronVersions, Installer, Runner } from '@electron/fiddle-core';
2✔
4
import { BrowserWindow, IpcMainEvent, WebContents } from 'electron';
2✔
5

6
import { ELECTRON_DOWNLOAD_PATH, ELECTRON_INSTALL_PATH } from './constants';
2✔
7
import { ipcMainManager } from './ipc';
2✔
8
import {
9
  DownloadVersionParams,
10
  ProgressObject,
11
  StartFiddleParams,
12
} from '../interfaces';
13
import { IpcEvents } from '../ipc-events';
2✔
14

15
let installer: Installer;
16
let runner: Runner;
17

18
// Keep track of which fiddle process belongs to which WebContents
19
const fiddleProcesses = new WeakMap<WebContents, ChildProcess>();
2✔
20

21
const downloadingVersions = new Map<string, Promise<any>>();
2✔
22
const removingVersions = new Map<string, Promise<void>>();
2✔
23

24
/**
25
 * Start running an Electron fiddle.
26
 */
27
export async function startFiddle(
2✔
28
  webContents: WebContents,
29
  params: StartFiddleParams,
30
): Promise<void> {
31
  const {
32
    dir,
33
    enableElectronLogging,
34
    isValidBuild,
35
    localPath,
36
    options,
37
    version,
38
  } = params;
3✔
39
  const env = { ...process.env };
3✔
40

41
  if (enableElectronLogging) {
3✔
42
    env.ELECTRON_ENABLE_LOGGING = 'true';
1✔
43
    env.ELECTRON_DEBUG_NOTIFICATIONS = 'true';
1✔
44
    env.ELECTRON_ENABLE_STACK_DUMPING = 'true';
1✔
45
  } else {
46
    delete env.ELECTRON_ENABLE_LOGGING;
2✔
47
    delete env.ELECTRON_DEBUG_NOTIFICATIONS;
2✔
48
    delete env.ELECTRON_ENABLE_STACK_DUMPING;
2✔
49
  }
50

51
  Object.assign(env, params.env);
3✔
52

53
  const child = await runner.spawn(
3✔
54
    isValidBuild && localPath ? Installer.getExecPath(localPath) : version,
9!
55
    dir,
56
    { args: options, cwd: dir, env },
57
  );
58
  fiddleProcesses.set(webContents, child);
3✔
59

60
  const pushOutput = (data: string | Buffer) => {
3✔
61
    ipcMainManager.send(
×
62
      IpcEvents.FIDDLE_RUNNER_OUTPUT,
63
      [data.toString()],
64
      webContents,
65
    );
66
  };
67

68
  child.stdout?.on('data', pushOutput);
3!
69
  child.stderr?.on('data', pushOutput);
3!
70

71
  child.on('close', async (code, signal) => {
3✔
72
    fiddleProcesses.delete(webContents);
×
73

74
    ipcMainManager.send(IpcEvents.FIDDLE_STOPPED, [code, signal], webContents);
×
75
  });
76
}
77

78
/**
79
 * Stop a currently running Electron fiddle.
80
 */
81
export function stopFiddle(webContents: WebContents): void {
2✔
82
  const child = fiddleProcesses.get(webContents);
×
83
  child?.kill();
×
84

85
  if (child) {
×
86
    // If the child process is still alive 1 second after we've
87
    // attempted to kill it by normal means, kill it forcefully.
88
    setTimeout(() => {
×
89
      if (child.exitCode === null) {
×
90
        child.kill('SIGKILL');
×
91
      }
92
    }, 1000);
93
  }
94
}
95

96
export async function setupFiddleCore(versions: ElectronVersions) {
2✔
97
  // For managing downloads and versions for electron
98
  installer = new Installer({
5✔
99
    electronDownloads: ELECTRON_DOWNLOAD_PATH,
100
    electronInstall: ELECTRON_INSTALL_PATH,
101
  });
102

103
  // Broadcast state changes to all windows
104
  installer.on('state-changed', (event) => {
5✔
105
    for (const window of BrowserWindow.getAllWindows()) {
×
106
      ipcMainManager.send(
×
107
        IpcEvents.VERSION_STATE_CHANGED,
108
        [event],
109
        window.webContents,
110
      );
111
    }
112
  });
113

114
  runner = await Runner.create({ installer, versions });
5✔
115

116
  ipcMainManager.on(
5✔
117
    IpcEvents.GET_VERSION_STATE,
118
    (event: IpcMainEvent, version: string) => {
119
      event.returnValue = installer.state(version);
×
120
    },
121
  );
122
  ipcMainManager.handle(
5✔
123
    IpcEvents.DOWNLOAD_VERSION,
124
    async (
125
      event: IpcMainEvent,
126
      version: string,
127
      opts?: Partial<DownloadVersionParams>,
128
    ) => {
129
      const webContents = event.sender;
×
130

131
      if (removingVersions.has(version)) {
×
132
        throw new Error('Version is being removed');
×
133
      }
134

135
      if (!downloadingVersions.has(version)) {
×
136
        const promise = installer.ensureDownloaded(version, {
×
137
          ...opts,
138
          progressCallback: (progress: ProgressObject) => {
139
            ipcMainManager.send(
×
140
              IpcEvents.VERSION_DOWNLOAD_PROGRESS,
141
              [version, progress],
142
              webContents,
143
            );
144
          },
145
        });
146

147
        downloadingVersions.set(version, promise);
×
148
      }
149

150
      try {
×
151
        await downloadingVersions.get(version);
×
152
      } finally {
153
        downloadingVersions.delete(version);
×
154
      }
155
    },
156
  );
157
  ipcMainManager.handle(
5✔
158
    IpcEvents.REMOVE_VERSION,
159
    async (_: IpcMainEvent, version: string) => {
160
      if (downloadingVersions.has(version)) {
×
161
        throw new Error('Version is being downloaded');
×
162
      }
163

164
      if (!removingVersions.has(version)) {
×
165
        removingVersions.set(version, installer.remove(version));
×
166
      }
167

168
      try {
×
169
        await removingVersions.get(version);
×
170
        return installer.state(version);
×
171
      } finally {
172
        removingVersions.delete(version);
×
173
      }
174
    },
175
  );
176
  ipcMainManager.handle(
5✔
177
    IpcEvents.START_FIDDLE,
178
    async (event: IpcMainEvent, params: StartFiddleParams) => {
179
      await startFiddle(event.sender, params);
×
180
    },
181
  );
182
  ipcMainManager.on(IpcEvents.STOP_FIDDLE, (event: IpcMainEvent) => {
5✔
183
    stopFiddle(event.sender);
×
184
  });
185
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc