@atom-js-org/runtime 0.2.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +31 -0
- package/README.md +17 -0
- package/index.d.ts +166 -0
- package/package.json +41 -0
- package/src/app.cjs +111 -0
- package/src/bridge-script.cjs +274 -0
- package/src/bridge-server.cjs +283 -0
- package/src/browser-window.cjs +411 -0
- package/src/clipboard.cjs +46 -0
- package/src/dialog.cjs +141 -0
- package/src/electron-apis.cjs +491 -0
- package/src/index.cjs +31 -0
- package/src/ipc-main.cjs +50 -0
- package/src/menu.cjs +48 -0
- package/src/runtime/macos-window-host.jxa.js +147 -0
- package/src/runtime/window-host.mjs +94 -0
- package/src/shell.cjs +42 -0
- package/src/state.cjs +11 -0
- package/src/web-contents.cjs +59 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { execFileSync, spawnSync } = require('node:child_process');
|
|
4
|
+
|
|
5
|
+
function writeText(text) {
|
|
6
|
+
const value = String(text);
|
|
7
|
+
if (process.platform === 'win32') {
|
|
8
|
+
const script = `Set-Clipboard -Value ${psQuote(value)}`;
|
|
9
|
+
execFileSync('powershell.exe', ['-NoProfile', '-Command', script]);
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
if (process.platform === 'darwin') {
|
|
13
|
+
const result = spawnSync('pbcopy', [], { input: value, encoding: 'utf8' });
|
|
14
|
+
if (result.error) throw result.error;
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
let result = spawnSync('wl-copy', [], { input: value, encoding: 'utf8' });
|
|
18
|
+
if (result.error && result.error.code === 'ENOENT') {
|
|
19
|
+
result = spawnSync('xclip', ['-selection', 'clipboard'], { input: value, encoding: 'utf8' });
|
|
20
|
+
}
|
|
21
|
+
if (result.error) throw new Error('Install wl-clipboard or xclip to use clipboard.writeText on Linux');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function readText() {
|
|
25
|
+
if (process.platform === 'win32') {
|
|
26
|
+
return execFileSync('powershell.exe', ['-NoProfile', '-Command', 'Get-Clipboard -Raw'], { encoding: 'utf8' }).replace(/\r?\n$/, '');
|
|
27
|
+
}
|
|
28
|
+
if (process.platform === 'darwin') {
|
|
29
|
+
return execFileSync('pbpaste', [], { encoding: 'utf8' });
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
return execFileSync('wl-paste', ['--no-newline'], { encoding: 'utf8' });
|
|
33
|
+
} catch {
|
|
34
|
+
try {
|
|
35
|
+
return execFileSync('xclip', ['-selection', 'clipboard', '-o'], { encoding: 'utf8' });
|
|
36
|
+
} catch {
|
|
37
|
+
throw new Error('Install wl-clipboard or xclip to use clipboard.readText on Linux');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function psQuote(value) {
|
|
43
|
+
return `'${String(value).replace(/'/g, "''")}'`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
module.exports = { writeText, readText };
|
package/src/dialog.cjs
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { execFile } = require('node:child_process');
|
|
4
|
+
const { promisify } = require('node:util');
|
|
5
|
+
const execFileAsync = promisify(execFile);
|
|
6
|
+
|
|
7
|
+
async function showOpenDialog(_browserWindowOrOptions, maybeOptions) {
|
|
8
|
+
const options = normalizeOptions(_browserWindowOrOptions, maybeOptions);
|
|
9
|
+
try {
|
|
10
|
+
const filePaths = await openDialogForPlatform(options);
|
|
11
|
+
return { canceled: filePaths.length === 0, filePaths };
|
|
12
|
+
} catch (error) {
|
|
13
|
+
if (isCancellation(error)) return { canceled: true, filePaths: [] };
|
|
14
|
+
throw error;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function showSaveDialog(_browserWindowOrOptions, maybeOptions) {
|
|
19
|
+
const options = normalizeOptions(_browserWindowOrOptions, maybeOptions);
|
|
20
|
+
try {
|
|
21
|
+
const filePath = await saveDialogForPlatform(options);
|
|
22
|
+
return { canceled: !filePath, filePath: filePath || undefined };
|
|
23
|
+
} catch (error) {
|
|
24
|
+
if (isCancellation(error)) return { canceled: true, filePath: undefined };
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function showMessageBox(_browserWindowOrOptions, maybeOptions) {
|
|
30
|
+
const options = normalizeOptions(_browserWindowOrOptions, maybeOptions);
|
|
31
|
+
const title = options.title || 'AtomJS';
|
|
32
|
+
const message = options.message || '';
|
|
33
|
+
|
|
34
|
+
if (process.platform === 'win32') {
|
|
35
|
+
const script = [
|
|
36
|
+
'Add-Type -AssemblyName PresentationFramework',
|
|
37
|
+
`[System.Windows.MessageBox]::Show(${psQuote(message)}, ${psQuote(title)}) | Out-Null`
|
|
38
|
+
].join('; ');
|
|
39
|
+
await execFileAsync('powershell.exe', ['-NoProfile', '-STA', '-Command', script]);
|
|
40
|
+
} else if (process.platform === 'darwin') {
|
|
41
|
+
await execFileAsync('osascript', ['-e', `display dialog ${appleQuote(message)} with title ${appleQuote(title)} buttons {"OK"} default button "OK"`]);
|
|
42
|
+
} else {
|
|
43
|
+
await execFileAsync('zenity', ['--info', `--title=${title}`, `--text=${message}`]);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return { response: 0, checkboxChecked: false };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function openDialogForPlatform(options) {
|
|
50
|
+
const multiple = Array.isArray(options.properties) && options.properties.includes('multiSelections');
|
|
51
|
+
|
|
52
|
+
if (process.platform === 'win32') {
|
|
53
|
+
const filter = toWindowsFilter(options.filters);
|
|
54
|
+
const script = [
|
|
55
|
+
'Add-Type -AssemblyName System.Windows.Forms',
|
|
56
|
+
'$d = New-Object System.Windows.Forms.OpenFileDialog',
|
|
57
|
+
`$d.Multiselect = $${multiple ? 'true' : 'false'}`,
|
|
58
|
+
options.defaultPath ? `$d.InitialDirectory = ${psQuote(options.defaultPath)}` : '',
|
|
59
|
+
filter ? `$d.Filter = ${psQuote(filter)}` : '',
|
|
60
|
+
'if ($d.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { $d.FileNames | ForEach-Object { Write-Output $_ } }'
|
|
61
|
+
].filter(Boolean).join('; ');
|
|
62
|
+
const { stdout } = await execFileAsync('powershell.exe', ['-NoProfile', '-STA', '-Command', script], { encoding: 'utf8' });
|
|
63
|
+
return splitLines(stdout);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (process.platform === 'darwin') {
|
|
67
|
+
const prompt = options.title || 'Choose a file';
|
|
68
|
+
const script = multiple
|
|
69
|
+
? `set chosenFiles to choose file with prompt ${appleQuote(prompt)} with multiple selections allowed\nset output to ""\nrepeat with f in chosenFiles\nset output to output & POSIX path of f & linefeed\nend repeat\nreturn output`
|
|
70
|
+
: `POSIX path of (choose file with prompt ${appleQuote(prompt)})`;
|
|
71
|
+
const { stdout } = await execFileAsync('osascript', ['-e', script], { encoding: 'utf8' });
|
|
72
|
+
return splitLines(stdout);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const args = ['--file-selection'];
|
|
76
|
+
if (options.title) args.push(`--title=${options.title}`);
|
|
77
|
+
if (options.defaultPath) args.push(`--filename=${options.defaultPath}`);
|
|
78
|
+
if (multiple) args.push('--multiple', '--separator=\n');
|
|
79
|
+
const { stdout } = await execFileAsync('zenity', args, { encoding: 'utf8' });
|
|
80
|
+
return splitLines(stdout);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function saveDialogForPlatform(options) {
|
|
84
|
+
if (process.platform === 'win32') {
|
|
85
|
+
const filter = toWindowsFilter(options.filters);
|
|
86
|
+
const script = [
|
|
87
|
+
'Add-Type -AssemblyName System.Windows.Forms',
|
|
88
|
+
'$d = New-Object System.Windows.Forms.SaveFileDialog',
|
|
89
|
+
options.defaultPath ? `$d.FileName = ${psQuote(options.defaultPath)}` : '',
|
|
90
|
+
filter ? `$d.Filter = ${psQuote(filter)}` : '',
|
|
91
|
+
'if ($d.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { Write-Output $d.FileName }'
|
|
92
|
+
].filter(Boolean).join('; ');
|
|
93
|
+
const { stdout } = await execFileAsync('powershell.exe', ['-NoProfile', '-STA', '-Command', script], { encoding: 'utf8' });
|
|
94
|
+
return stdout.trim();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (process.platform === 'darwin') {
|
|
98
|
+
const defaultName = options.defaultPath ? String(options.defaultPath).split(/[\\/]/).pop() : 'Untitled';
|
|
99
|
+
const script = `POSIX path of (choose file name with prompt ${appleQuote(options.title || 'Save file')} default name ${appleQuote(defaultName)})`;
|
|
100
|
+
const { stdout } = await execFileAsync('osascript', ['-e', script], { encoding: 'utf8' });
|
|
101
|
+
return stdout.trim();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const args = ['--file-selection', '--save', '--confirm-overwrite'];
|
|
105
|
+
if (options.title) args.push(`--title=${options.title}`);
|
|
106
|
+
if (options.defaultPath) args.push(`--filename=${options.defaultPath}`);
|
|
107
|
+
const { stdout } = await execFileAsync('zenity', args, { encoding: 'utf8' });
|
|
108
|
+
return stdout.trim();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function normalizeOptions(first, second) {
|
|
112
|
+
if (second && typeof second === 'object') return second;
|
|
113
|
+
if (first && typeof first === 'object' && !('webContents' in first)) return first;
|
|
114
|
+
return {};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function toWindowsFilter(filters) {
|
|
118
|
+
if (!Array.isArray(filters) || filters.length === 0) return '';
|
|
119
|
+
return filters.map((filter) => {
|
|
120
|
+
const extensions = (filter.extensions || ['*']).map((ext) => ext === '*' ? '*.*' : `*.${ext}`).join(';');
|
|
121
|
+
return `${filter.name || 'Files'}|${extensions}`;
|
|
122
|
+
}).join('|');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function splitLines(value) {
|
|
126
|
+
return String(value || '').split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function isCancellation(error) {
|
|
130
|
+
return error && (error.code === 1 || error.code === 'ENOENT' || /cancel/i.test(error.stderr || ''));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function psQuote(value) {
|
|
134
|
+
return `'${String(value).replace(/'/g, "''")}'`;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function appleQuote(value) {
|
|
138
|
+
return JSON.stringify(String(value));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
module.exports = { showOpenDialog, showSaveDialog, showMessageBox };
|
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { EventEmitter } = require('node:events');
|
|
4
|
+
const { MessageChannel, MessagePort } = require('node:worker_threads');
|
|
5
|
+
const childProcess = require('node:child_process');
|
|
6
|
+
const http = require('node:http');
|
|
7
|
+
const https = require('node:https');
|
|
8
|
+
const path = require('node:path');
|
|
9
|
+
const fs = require('node:fs');
|
|
10
|
+
const state = require('./state.cjs');
|
|
11
|
+
const { BrowserWindow } = require('./browser-window.cjs');
|
|
12
|
+
const { WebContents } = require('./web-contents.cjs');
|
|
13
|
+
|
|
14
|
+
function compatibilityWarning(api) {
|
|
15
|
+
console.warn(`[AtomJS Electron compatibility] ${api} is currently a compatibility stub.`);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
class NativeImage {
|
|
19
|
+
constructor(source = null) {
|
|
20
|
+
this._source = source;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
isEmpty() {
|
|
24
|
+
return this._source == null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
getSize() {
|
|
28
|
+
return { width: 0, height: 0 };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
toPNG() {
|
|
32
|
+
if (Buffer.isBuffer(this._source)) return Buffer.from(this._source);
|
|
33
|
+
return Buffer.alloc(0);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
toJPEG() {
|
|
37
|
+
return this.toPNG();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
toDataURL() {
|
|
41
|
+
if (typeof this._source === 'string' && this._source.startsWith('data:')) return this._source;
|
|
42
|
+
const data = this.toPNG();
|
|
43
|
+
return `data:image/png;base64,${data.toString('base64')}`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
getNativeHandle() {
|
|
47
|
+
return Buffer.alloc(0);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
resize() {
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
crop() {
|
|
55
|
+
return this;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
addRepresentation() {}
|
|
59
|
+
|
|
60
|
+
setTemplateImage() {}
|
|
61
|
+
|
|
62
|
+
isTemplateImage() {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const nativeImage = {
|
|
68
|
+
createEmpty: () => new NativeImage(),
|
|
69
|
+
createFromPath(filePath) {
|
|
70
|
+
const absolute = path.resolve(String(filePath));
|
|
71
|
+
return new NativeImage(fs.existsSync(absolute) ? absolute : null);
|
|
72
|
+
},
|
|
73
|
+
createFromBuffer(buffer) {
|
|
74
|
+
return new NativeImage(Buffer.from(buffer || []));
|
|
75
|
+
},
|
|
76
|
+
createFromDataURL(dataUrl) {
|
|
77
|
+
return new NativeImage(String(dataUrl));
|
|
78
|
+
},
|
|
79
|
+
createFromNamedImage(name) {
|
|
80
|
+
return new NativeImage(String(name));
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
class Notification extends EventEmitter {
|
|
85
|
+
constructor(options = {}) {
|
|
86
|
+
super();
|
|
87
|
+
this.title = options.title || '';
|
|
88
|
+
this.body = options.body || '';
|
|
89
|
+
this.options = { ...options };
|
|
90
|
+
this._shown = false;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
show() {
|
|
94
|
+
this._shown = true;
|
|
95
|
+
queueMicrotask(() => this.emit('show'));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
close() {
|
|
99
|
+
if (!this._shown) return;
|
|
100
|
+
this._shown = false;
|
|
101
|
+
queueMicrotask(() => this.emit('close'));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
static isSupported() {
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
class Session extends EventEmitter {
|
|
110
|
+
constructor(partition = 'default') {
|
|
111
|
+
super();
|
|
112
|
+
this.partition = partition;
|
|
113
|
+
this.webRequest = createWebRequest();
|
|
114
|
+
this.cookies = createCookieStore();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
clearCache() {
|
|
118
|
+
return Promise.resolve();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
clearStorageData() {
|
|
122
|
+
return Promise.resolve();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
flushStorageData() {}
|
|
126
|
+
|
|
127
|
+
getCacheSize() {
|
|
128
|
+
return Promise.resolve(0);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
setProxy() {
|
|
132
|
+
return Promise.resolve();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
resolveProxy() {
|
|
136
|
+
return Promise.resolve('DIRECT');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
setPermissionRequestHandler(handler) {
|
|
140
|
+
this._permissionRequestHandler = handler;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
setPermissionCheckHandler(handler) {
|
|
144
|
+
this._permissionCheckHandler = handler;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
setUserAgent() {}
|
|
148
|
+
|
|
149
|
+
getUserAgent() {
|
|
150
|
+
return `AtomJS/${process.versions.atomjs || '0.2.0'} SystemWebView`;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function createWebRequest() {
|
|
155
|
+
const handlers = new Map();
|
|
156
|
+
const api = {};
|
|
157
|
+
for (const name of [
|
|
158
|
+
'onBeforeRequest',
|
|
159
|
+
'onBeforeSendHeaders',
|
|
160
|
+
'onSendHeaders',
|
|
161
|
+
'onHeadersReceived',
|
|
162
|
+
'onResponseStarted',
|
|
163
|
+
'onBeforeRedirect',
|
|
164
|
+
'onCompleted',
|
|
165
|
+
'onErrorOccurred'
|
|
166
|
+
]) {
|
|
167
|
+
api[name] = (...args) => {
|
|
168
|
+
const listener = args.find((arg) => typeof arg === 'function') || null;
|
|
169
|
+
handlers.set(name, listener);
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
api._handlers = handlers;
|
|
173
|
+
return api;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function createCookieStore() {
|
|
177
|
+
const entries = [];
|
|
178
|
+
return {
|
|
179
|
+
async get(filter = {}) {
|
|
180
|
+
return entries.filter((entry) => Object.entries(filter).every(([key, value]) => entry[key] === value));
|
|
181
|
+
},
|
|
182
|
+
async set(details) {
|
|
183
|
+
entries.push({ ...details });
|
|
184
|
+
},
|
|
185
|
+
async remove(url, name) {
|
|
186
|
+
for (let index = entries.length - 1; index >= 0; index--) {
|
|
187
|
+
if (entries[index].url === url && entries[index].name === name) entries.splice(index, 1);
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
async flushStore() {}
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const sessions = new Map();
|
|
195
|
+
const session = {
|
|
196
|
+
get defaultSession() {
|
|
197
|
+
return session.fromPartition('default');
|
|
198
|
+
},
|
|
199
|
+
fromPartition(partition = 'default') {
|
|
200
|
+
const key = String(partition);
|
|
201
|
+
if (!sessions.has(key)) sessions.set(key, new Session(key));
|
|
202
|
+
return sessions.get(key);
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const protocolHandlers = new Map();
|
|
207
|
+
const protocol = {
|
|
208
|
+
registerSchemesAsPrivileged() {},
|
|
209
|
+
registerFileProtocol(scheme, handler) {
|
|
210
|
+
protocolHandlers.set(String(scheme), handler);
|
|
211
|
+
},
|
|
212
|
+
registerBufferProtocol(scheme, handler) {
|
|
213
|
+
protocolHandlers.set(String(scheme), handler);
|
|
214
|
+
},
|
|
215
|
+
registerStringProtocol(scheme, handler) {
|
|
216
|
+
protocolHandlers.set(String(scheme), handler);
|
|
217
|
+
},
|
|
218
|
+
handle(scheme, handler) {
|
|
219
|
+
protocolHandlers.set(String(scheme), handler);
|
|
220
|
+
},
|
|
221
|
+
unhandle(scheme) {
|
|
222
|
+
protocolHandlers.delete(String(scheme));
|
|
223
|
+
},
|
|
224
|
+
unregisterProtocol(scheme) {
|
|
225
|
+
protocolHandlers.delete(String(scheme));
|
|
226
|
+
return Promise.resolve();
|
|
227
|
+
},
|
|
228
|
+
isProtocolHandled(scheme) {
|
|
229
|
+
return Promise.resolve(protocolHandlers.has(String(scheme)));
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
const shortcuts = new Map();
|
|
234
|
+
const globalShortcut = {
|
|
235
|
+
register(accelerator, callback) {
|
|
236
|
+
shortcuts.set(String(accelerator), callback);
|
|
237
|
+
compatibilityWarning('globalShortcut.register');
|
|
238
|
+
return false;
|
|
239
|
+
},
|
|
240
|
+
registerAll(accelerators, callback) {
|
|
241
|
+
for (const accelerator of accelerators || []) shortcuts.set(String(accelerator), callback);
|
|
242
|
+
},
|
|
243
|
+
isRegistered(accelerator) {
|
|
244
|
+
return shortcuts.has(String(accelerator));
|
|
245
|
+
},
|
|
246
|
+
unregister(accelerator) {
|
|
247
|
+
shortcuts.delete(String(accelerator));
|
|
248
|
+
},
|
|
249
|
+
unregisterAll() {
|
|
250
|
+
shortcuts.clear();
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
let powerSaveSequence = 0;
|
|
255
|
+
const powerSaveIds = new Set();
|
|
256
|
+
const powerSaveBlocker = {
|
|
257
|
+
start() {
|
|
258
|
+
const id = ++powerSaveSequence;
|
|
259
|
+
powerSaveIds.add(id);
|
|
260
|
+
return id;
|
|
261
|
+
},
|
|
262
|
+
stop(id) {
|
|
263
|
+
return powerSaveIds.delete(Number(id));
|
|
264
|
+
},
|
|
265
|
+
isStarted(id) {
|
|
266
|
+
return powerSaveIds.has(Number(id));
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
const primaryDisplay = {
|
|
271
|
+
id: 1,
|
|
272
|
+
rotation: 0,
|
|
273
|
+
scaleFactor: 1,
|
|
274
|
+
touchSupport: 'unknown',
|
|
275
|
+
monochrome: false,
|
|
276
|
+
accelerometerSupport: 'unknown',
|
|
277
|
+
colorSpace: 'unknown',
|
|
278
|
+
colorDepth: 24,
|
|
279
|
+
depthPerComponent: 8,
|
|
280
|
+
bounds: { x: 0, y: 0, width: 1920, height: 1080 },
|
|
281
|
+
workArea: { x: 0, y: 0, width: 1920, height: 1040 },
|
|
282
|
+
size: { width: 1920, height: 1080 },
|
|
283
|
+
workAreaSize: { width: 1920, height: 1040 },
|
|
284
|
+
internal: true
|
|
285
|
+
};
|
|
286
|
+
const screen = Object.assign(new EventEmitter(), {
|
|
287
|
+
getCursorScreenPoint: () => ({ x: 0, y: 0 }),
|
|
288
|
+
getPrimaryDisplay: () => ({ ...primaryDisplay }),
|
|
289
|
+
getAllDisplays: () => [{ ...primaryDisplay }],
|
|
290
|
+
getDisplayNearestPoint: () => ({ ...primaryDisplay }),
|
|
291
|
+
getDisplayMatching: () => ({ ...primaryDisplay })
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
const net = {
|
|
295
|
+
fetch(input, init) {
|
|
296
|
+
return globalThis.fetch(input, init);
|
|
297
|
+
},
|
|
298
|
+
isOnline() {
|
|
299
|
+
return true;
|
|
300
|
+
},
|
|
301
|
+
request(options) {
|
|
302
|
+
const target = typeof options === 'string' || options instanceof URL ? options : options.url || options;
|
|
303
|
+
const transport = String(target).startsWith('https:') ? https : http;
|
|
304
|
+
return transport.request(options);
|
|
305
|
+
},
|
|
306
|
+
resolveHost(host) {
|
|
307
|
+
return Promise.resolve({ endpoints: [{ address: String(host), family: 'unspecified' }] });
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
const safeStorage = {
|
|
312
|
+
isEncryptionAvailable() {
|
|
313
|
+
return false;
|
|
314
|
+
},
|
|
315
|
+
encryptString() {
|
|
316
|
+
throw new Error('AtomJS safeStorage is unavailable until a platform keychain adapter is installed.');
|
|
317
|
+
},
|
|
318
|
+
decryptString() {
|
|
319
|
+
throw new Error('AtomJS safeStorage is unavailable until a platform keychain adapter is installed.');
|
|
320
|
+
},
|
|
321
|
+
setUsePlainTextEncryption() {}
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
const desktopCapturer = {
|
|
325
|
+
async getSources() {
|
|
326
|
+
compatibilityWarning('desktopCapturer.getSources');
|
|
327
|
+
return [];
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
const systemPreferences = Object.assign(new EventEmitter(), {
|
|
332
|
+
isDarkMode: () => false,
|
|
333
|
+
isSwipeTrackingFromScrollEventsEnabled: () => false,
|
|
334
|
+
getAccentColor: () => '000000',
|
|
335
|
+
getColor: () => '#000000',
|
|
336
|
+
getSystemColor: () => '#000000',
|
|
337
|
+
askForMediaAccess: async () => false,
|
|
338
|
+
getMediaAccessStatus: () => 'not-determined',
|
|
339
|
+
canPromptTouchID: () => false,
|
|
340
|
+
promptTouchID: async () => { throw new Error('Touch ID is not available through the AtomJS pure-JavaScript runtime.'); }
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
const powerMonitor = Object.assign(new EventEmitter(), {
|
|
344
|
+
getSystemIdleState: () => 'active',
|
|
345
|
+
getSystemIdleTime: () => 0,
|
|
346
|
+
isOnBatteryPower: () => false
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
const crashReporter = {
|
|
350
|
+
start() {},
|
|
351
|
+
getLastCrashReport: () => null,
|
|
352
|
+
getUploadedReports: () => [],
|
|
353
|
+
getUploadToServer: () => false,
|
|
354
|
+
setUploadToServer() {},
|
|
355
|
+
addExtraParameter() {},
|
|
356
|
+
removeExtraParameter() {},
|
|
357
|
+
getParameters: () => ({}),
|
|
358
|
+
getCrashesDirectory: () => ''
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
const autoUpdater = Object.assign(new EventEmitter(), {
|
|
362
|
+
setFeedURL() {},
|
|
363
|
+
getFeedURL: () => '',
|
|
364
|
+
checkForUpdates() {
|
|
365
|
+
const error = new Error('AtomJS autoUpdater is not configured.');
|
|
366
|
+
queueMicrotask(() => autoUpdater.emit('error', error));
|
|
367
|
+
return Promise.reject(error);
|
|
368
|
+
},
|
|
369
|
+
quitAndInstall() {}
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
const contentTracing = {
|
|
373
|
+
getCategories: async () => [],
|
|
374
|
+
startRecording: async () => {},
|
|
375
|
+
stopRecording: async () => ''
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
const netLog = {
|
|
379
|
+
startLogging: async () => {},
|
|
380
|
+
stopLogging: async () => ''
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
const utilityProcess = {
|
|
384
|
+
fork(modulePath, args = [], options = {}) {
|
|
385
|
+
return childProcess.fork(modulePath, args, options);
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
class MessageChannelMain {
|
|
390
|
+
constructor() {
|
|
391
|
+
const channel = new MessageChannel();
|
|
392
|
+
this.port1 = channel.port1;
|
|
393
|
+
this.port2 = channel.port2;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
class BrowserView extends EventEmitter {
|
|
398
|
+
constructor(options = {}) {
|
|
399
|
+
super();
|
|
400
|
+
this.webContents = new WebContents({
|
|
401
|
+
id: -Date.now(),
|
|
402
|
+
isDestroyed: () => false,
|
|
403
|
+
_currentUrl: '',
|
|
404
|
+
options
|
|
405
|
+
});
|
|
406
|
+
this._bounds = { x: 0, y: 0, width: 0, height: 0 };
|
|
407
|
+
}
|
|
408
|
+
setBounds(bounds) { this._bounds = { ...this._bounds, ...bounds }; }
|
|
409
|
+
getBounds() { return { ...this._bounds }; }
|
|
410
|
+
setAutoResize() {}
|
|
411
|
+
setBackgroundColor() {}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
class WebContentsView extends BrowserView {}
|
|
415
|
+
class View extends EventEmitter {}
|
|
416
|
+
class ImageView extends View {}
|
|
417
|
+
class BaseWindow extends BrowserWindow {}
|
|
418
|
+
|
|
419
|
+
class TouchBar {
|
|
420
|
+
constructor(options = {}) { Object.assign(this, options); }
|
|
421
|
+
}
|
|
422
|
+
for (const name of ['TouchBarButton', 'TouchBarColorPicker', 'TouchBarGroup', 'TouchBarLabel', 'TouchBarOtherItemsProxy', 'TouchBarPopover', 'TouchBarScrubber', 'TouchBarSegmentedControl', 'TouchBarSlider', 'TouchBarSpacer']) {
|
|
423
|
+
TouchBar[name] = class { constructor(options = {}) { Object.assign(this, options); } };
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
const webContents = {
|
|
427
|
+
getAllWebContents() {
|
|
428
|
+
return BrowserWindow.getAllWindows().map((window) => window.webContents);
|
|
429
|
+
},
|
|
430
|
+
getFocusedWebContents() {
|
|
431
|
+
const window = BrowserWindow.getFocusedWindow();
|
|
432
|
+
return window ? window.webContents : null;
|
|
433
|
+
},
|
|
434
|
+
fromId(id) {
|
|
435
|
+
return webContents.getAllWebContents().find((contents) => contents.id === Number(id)) || null;
|
|
436
|
+
},
|
|
437
|
+
fromFrame() {
|
|
438
|
+
return null;
|
|
439
|
+
},
|
|
440
|
+
fromDevToolsTargetId() {
|
|
441
|
+
return null;
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
const pushNotifications = Object.assign(new EventEmitter(), {
|
|
446
|
+
registerForAPNSNotifications: async () => {},
|
|
447
|
+
unregisterForAPNSNotifications() {}
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
const inAppPurchase = Object.assign(new EventEmitter(), {
|
|
451
|
+
canMakePayments: () => false,
|
|
452
|
+
getProducts: async () => [],
|
|
453
|
+
purchaseProduct: async () => false,
|
|
454
|
+
restoreCompletedTransactions() {},
|
|
455
|
+
getReceiptURL: () => ''
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
const parentPort = null;
|
|
459
|
+
|
|
460
|
+
module.exports = {
|
|
461
|
+
BaseWindow,
|
|
462
|
+
BrowserView,
|
|
463
|
+
WebContentsView,
|
|
464
|
+
View,
|
|
465
|
+
ImageView,
|
|
466
|
+
Notification,
|
|
467
|
+
Session,
|
|
468
|
+
TouchBar,
|
|
469
|
+
MessageChannelMain,
|
|
470
|
+
MessagePortMain: MessagePort,
|
|
471
|
+
autoUpdater,
|
|
472
|
+
contentTracing,
|
|
473
|
+
crashReporter,
|
|
474
|
+
desktopCapturer,
|
|
475
|
+
globalShortcut,
|
|
476
|
+
inAppPurchase,
|
|
477
|
+
nativeImage,
|
|
478
|
+
net,
|
|
479
|
+
netLog,
|
|
480
|
+
parentPort,
|
|
481
|
+
powerMonitor,
|
|
482
|
+
powerSaveBlocker,
|
|
483
|
+
protocol,
|
|
484
|
+
pushNotifications,
|
|
485
|
+
safeStorage,
|
|
486
|
+
screen,
|
|
487
|
+
session,
|
|
488
|
+
systemPreferences,
|
|
489
|
+
utilityProcess,
|
|
490
|
+
webContents
|
|
491
|
+
};
|
package/src/index.cjs
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const app = require('./app.cjs');
|
|
4
|
+
const { BrowserWindow } = require('./browser-window.cjs');
|
|
5
|
+
const ipcMain = require('./ipc-main.cjs');
|
|
6
|
+
const dialog = require('./dialog.cjs');
|
|
7
|
+
const shell = require('./shell.cjs');
|
|
8
|
+
const clipboard = require('./clipboard.cjs');
|
|
9
|
+
const { Menu, MenuItem, Tray } = require('./menu.cjs');
|
|
10
|
+
const electronApis = require('./electron-apis.cjs');
|
|
11
|
+
|
|
12
|
+
const nativeTheme = {
|
|
13
|
+
get shouldUseDarkColors() {
|
|
14
|
+
return process.env.ATOM_THEME === 'dark';
|
|
15
|
+
},
|
|
16
|
+
themeSource: 'system'
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
module.exports = {
|
|
20
|
+
app,
|
|
21
|
+
BrowserWindow,
|
|
22
|
+
ipcMain,
|
|
23
|
+
dialog,
|
|
24
|
+
shell,
|
|
25
|
+
clipboard,
|
|
26
|
+
Menu,
|
|
27
|
+
MenuItem,
|
|
28
|
+
Tray,
|
|
29
|
+
nativeTheme,
|
|
30
|
+
...electronApis
|
|
31
|
+
};
|