Repository navigation
Expand file tree
/
Copy pathipc-compat.js
More file actions
129 lines (113 loc) · 4.57 KB
/
Copy pathipc-compat.js
File metadata and controls
129 lines (113 loc) · 4.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/**
* IPC Compatibility Layer
* Provides backward compatibility wrapper for old ipcRenderer code
* Maps old ipcRenderer calls to new secure electronAPI
*
* ES-модуль без экспорта (план 2026-10-30-es-modules): его импортирует
* каждый вход окна и *-theme-sync.js ПЕРВЫМ импортом — `window.ipcRenderer`
* готов до кода окна. Сам шим остаётся глобалом: его зовут окна и e2e
* (крючок e2e, tests/window-bridges.test.js PERMANENT).
*/
(function() {
'use strict';
// Node: тесты делают require(esm) display-script.js ради чистых помощников,
// и граф импорта приводит сюда — окна там нет, шим не нужен.
if (typeof window === 'undefined') {
return;
}
// Check if electronAPI is available (from preload.js)
if (typeof window.electronAPI === 'undefined') {
console.error('electronAPI not available! Make sure preload.js is loaded.');
return;
}
// Create compatibility shim for ipcRenderer
window.ipcRenderer = {
/**
* Send message to main process
* @param {string} channel - Channel name
* @param {any} [data] - Data to send (тип по каналу — globals.d.ts)
*/
send: function(channel, data) {
window.electronAPI.send(channel, data);
},
/**
* Register event listener
* @param {string} channel - Channel name
* @param {Function} callback - Callback function (event, ...args) => void
* @returns {() => void} - Cleanup function
*/
on: function(channel, callback) {
// Wrap callback to match old ipcRenderer signature (event, ...args)
const wrappedCallback = function(...args) {
// Create a fake event object for compatibility
const fakeEvent = { sender: null };
callback(fakeEvent, ...args);
};
// Store the cleanup function
const cleanup = window.electronAPI.on(channel, wrappedCallback);
// Store reference for removeListener
if (!this._listeners.has(channel)) {
this._listeners.set(channel, []);
}
this._listeners.get(channel).push({
original: callback,
wrapped: wrappedCallback,
cleanup: cleanup
});
return cleanup;
},
/**
* Register one-time event listener
* @param {string} channel - Channel name
* @param {Function} callback - Callback function
*/
once: function(channel, callback) {
const wrappedCallback = function(...args) {
const fakeEvent = { sender: null };
callback(fakeEvent, ...args);
};
window.electronAPI.once(channel, wrappedCallback);
},
/**
* Remove specific event listener
* @param {string} channel - Channel name
* @param {Function} callback - Original callback function
*/
removeListener: function(channel, callback) {
if (!this._listeners || !this._listeners.has(channel)) {
return;
}
const listeners = this._listeners.get(channel);
const target = listeners.find(l => l.original === callback);
if (target) {
target.cleanup();
const remaining = listeners.filter(l => l.original !== callback);
if (remaining.length === 0) {
this._listeners.delete(channel);
} else {
this._listeners.set(channel, remaining);
}
}
},
/**
* Remove all listeners for a channel
* @param {string} channel - Channel name
*/
removeAllListeners: function(channel) {
if (this._listeners && this._listeners.has(channel)) {
const listeners = this._listeners.get(channel);
// Call all cleanup functions
listeners.forEach(l => l.cleanup());
this._listeners.delete(channel);
}
window.electronAPI.removeAllListeners(channel);
},
/**
* Internal storage for listener references
* @private
*/
_listeners: new Map()
};
// Freeze the ipcRenderer object to prevent modifications
Object.freeze(window.ipcRenderer);
})();