Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ci: update to electron 17 #36

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
]
},
"rules": {
"max-len": ["error", { "code": 120 }],
"indent": [
2,
4,
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ event name|payload|description
`beforfeLoadUrl`|`(port, lastPort)`|emitted before `webContents.loadURL` is invoked, in other words just before loading the Meteor app; `port` - the port on which the app is served, `lastPort` - the port on which the app was served previously (when HCP is applied)
`beforeReload`|`(pendingVersion, containsDesktopUpdate)`|emitted just before HCP reload
`moduleLoadFailed`|`(dirName, error)`|emitted if a module failed to load
`childWindow`|`(openWindowHandlerResult, details)`| emitted when child window is created. Gives possibility to reject or set up BrowserWindowConstructorOptions. For details see [setWindowOpenHandler](https://www.electronjs.org/docs/latest/api/web-contents#contentssetwindowopenhandlerhandler)

Your can also emit events on this bus as well. A good practice is to namespace them using dots,
like for instance `myModule.initalized`.
Expand Down
6 changes: 3 additions & 3 deletions lib/defaultDependencies.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module.exports = {
electron: '11.5.0',
'electron-builder': '23.3.1',
'electron-packager': '15.4.0'
electron: '17.4.11',
'electron-builder': '24.6.4',
'electron-packager': '17.1.2'
};
2,188 changes: 984 additions & 1,204 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
"sha1-file": "1.0.4",
"sinon": "2.4.1",
"sinon-chai": "2.14.0",
"spectron": "13.0.0",
"spectron": "19.0.0",
"temp-dir": "2.0.0",
"watch": "1.0.2"
},
Expand Down
76 changes: 47 additions & 29 deletions skeleton/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,16 @@ export default class App {
if (!this.isProduction()) {
nodeModulesPath.splice(1, 0, '..');
}
require('module').globalPaths.push(path.resolve(join(...nodeModulesPath)));

const GlobalModule = require('module');
const absoluteNodeModulesPath = path.resolve(join(...nodeModulesPath));
// for electron 16 or lower
GlobalModule.globalPaths.push(absoluteNodeModulesPath);
// for electron 17 or higher
// eslint-disable-next-line no-underscore-dangle
const nodeModulePaths = GlobalModule._nodeModulePaths;
// eslint-disable-next-line no-underscore-dangle
GlobalModule._nodeModulePaths = (from) => nodeModulePaths(from).concat([absoluteNodeModulesPath]);

/**
* DEPRECATED
Expand Down Expand Up @@ -182,8 +191,8 @@ export default class App {
);
} catch (e) {
this.l.error(e);
dialog.showErrorBox('Application', 'Could not read settings.json. Please reinstall' +
' this application.');
dialog.showErrorBox('Application', 'Could not read settings.json. Please reinstall'
+ ' this application.');

if (this.app && this.app.quit) {
this.app.quit();
Expand Down Expand Up @@ -235,13 +244,12 @@ export default class App {
// Empty catch block... nasty...
}
setTimeout(() => {
dialog.showErrorBox('Application', 'Internal error occurred. Restart this ' +
'application. If the problem persists, contact support or try to reinstall.');
dialog.showErrorBox('Application', 'Internal error occurred. Restart this '
+ 'application. If the problem persists, contact support or try to reinstall.');
this.app.quit();
}, 500);
}


/**
* Applies dev, os specific and variables to window settings.
*/
Expand Down Expand Up @@ -274,8 +282,8 @@ export default class App {
appSettings: this.settings,
eventsBus: this.eventsBus,
modules: this.modules,
settings: typeof this.settings.plugins[plugin] === 'object' ?
this.settings.plugins[plugin] : {},
settings: typeof this.settings.plugins[plugin] === 'object'
? this.settings.plugins[plugin] : {},
Module
});
} catch (e) {
Expand Down Expand Up @@ -304,7 +312,7 @@ export default class App {
moduleDirectories = fs.readdirSync(join(this.desktopPath, 'modules'));
} catch (err) {
if (err.code === 'ENOENT') {
this.l.debug(`not loading custom app modules because .desktop/modules isn't a directory`);
this.l.debug('not loading custom app modules because .desktop/modules isn\'t a directory');
} else {
throw err;
}
Expand Down Expand Up @@ -343,8 +351,7 @@ export default class App {
}
// Inject extractedFilesPath.
if ('extract' in moduleJson) {
settings.extractedFilesPath =
join(__dirname, '..', 'extracted', moduleName);
settings.extractedFilesPath = join(__dirname, '..', 'extracted', moduleName);
}
return { settings, moduleName };
}
Expand All @@ -358,7 +365,7 @@ export default class App {
loadModule(internal, modulePath, dirName = '') {
let moduleName = path.parse(modulePath).name;
let settings = {};
let indexPath = '';
let indexPath;

if (!internal) {
// module.json is mandatory, but we can live without it.
Expand Down Expand Up @@ -407,7 +414,6 @@ export default class App {
loadDesktopJs() {
try {
const desktopJsPath = join(this.desktopPath, 'desktop.js');

const Desktop = require(desktopJsPath).default;
this.desktop = new Desktop({
log: this.loggerManager.configureLogger('desktop'),
Expand Down Expand Up @@ -472,7 +478,6 @@ export default class App {
return Promise.all(promises);
}


/**
* Initializes this app.
* Loads plugins.
Expand Down Expand Up @@ -543,8 +548,7 @@ export default class App {
bundleStorePath: this.userDataDir,
customHCPUrl: this.settings.customHCPUrl || null,
initialBundlePath: path.join(__dirname, '..', 'meteor.asar'),
webAppStartupTimeout: this.settings.webAppStartupTimeout ?
this.settings.webAppStartupTimeout : 20000
webAppStartupTimeout: this.settings.webAppStartupTimeout ? this.settings.webAppStartupTimeout : 20000
};
}

Expand All @@ -554,8 +558,8 @@ export default class App {
*/
onStartupFailed(code) {
this.emit('startupFailed');
dialog.showErrorBox('Startup error', 'Could not initialize app. Please contact' +
` your support. Error code: ${code}`);
dialog.showErrorBox('Startup error', 'Could not initialize app. Please contact'
+ ` your support. Error code: ${code}`);
this.app.quit();
}

Expand All @@ -582,7 +586,7 @@ export default class App {
// this way.
this.emit('windowSettings', windowSettings);

windowSettings.webPreferences.nodeIntegration = false; // node integration must to be off
windowSettings.webPreferences.nodeIntegration = false; // node integration must be off
windowSettings.webPreferences.preload = join(__dirname, 'preload.js');
windowSettings.webPreferences.enableRemoteModule = true; // needed since Electron 10

Expand All @@ -605,14 +609,30 @@ export default class App {
box-shadow:0 1px 0 rgba(255,255,255,0.4) inset,0 5px 3px -5px rgba(0,0,0,0.5),
0 -13px 5px -10px rgba(255,255,255,0.4) inset;
line-height:20px;text-align:center;font-weight:700;font-size:20px\`);
console.log(\`%cdesktop version: ${this.settings.desktopVersion}\\n` +
`desktop compatibility version: ${this.settings.compatibilityVersion}\\n` +
'meteor bundle version:' +
` ${this.modules.autoupdate.currentAssetBundle.getVersion()}\\n\`` +
', \'font-size: 9px;color:#222\');');
console.log(\`%cdesktop version: ${this.settings.desktopVersion}\\n`
+ `desktop compatibility version: ${this.settings.compatibilityVersion}\\n`
+ 'meteor bundle version:'
+ ` ${this.modules.autoupdate.currentAssetBundle.getVersion()}\\n\``
+ ', \'font-size: 9px;color:#222\');');
});
}

this.webContents.setWindowOpenHandler((details) => {
const { url } = details;
const overrideOptions = url.startsWith('meteor://') ? {
overrideBrowserWindowOptions: {
webPreferences: windowSettings.webPreferences,
parent: this.window
}
} : {};
const result = {
action: 'allow',
...overrideOptions
};
this.emit('childWindow', result, details);
return result;
});

this.emit('windowCreated', this.window);

// Here we are catching reloads triggered by hot code push.
Expand Down Expand Up @@ -640,7 +660,7 @@ export default class App {
(request, callback) => {
const url = request.url.substr(urlStripLength);
this.modules.localServer.getStreamProtocolResponse(url)
.then(res => callback(res))
.then((res) => callback(res))
.catch((e) => {
callback(this.modules.localServer.getServerErrorResponse());
this.log.error(`error while trying to fetch ${url}: ${e.toString()}`);
Expand Down Expand Up @@ -676,8 +696,7 @@ export default class App {
}
if (!this.windowAlreadyLoaded) {
if (this.meteorAppVersionChange) {
this.l.verbose('there is a new version downloaded already, performing HCP' +
' reset');
this.l.verbose('there is a new version downloaded already, performing HCP reset');
this.updateToNewVersion();
} else {
this.windowAlreadyLoaded = true;
Expand All @@ -700,8 +719,7 @@ export default class App {

this.l.verbose(`${this.settings.desktopVersion} !== ${this.pendingDesktopVersion}`);

const desktopUpdate = this.settings.desktopHCP &&
this.settings.desktopVersion !== this.pendingDesktopVersion;
const desktopUpdate = this.settings.desktopHCP && this.settings.desktopVersion !== this.pendingDesktopVersion;

this.emit(
'beforeReload', this.modules.autoupdate.getPendingVersion(), desktopUpdate
Expand Down
49 changes: 33 additions & 16 deletions skeleton/preload.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// This was inspiried by
// https://github.com/electron-webapps/meteor-electron/blob/master/app/preload.js
const ipc = require('electron').ipcRenderer;
const { contextBridge } = require('electron');

const exposedModules = [];
/**
Expand Down Expand Up @@ -29,6 +30,7 @@ const Desktop = new (class {
this.fetchCallCounter = 0;
this.fetchTimeoutTimers = {};
this.fetchTimeout = 2000;
this.electron = {};
}

/**
Expand Down Expand Up @@ -81,12 +83,11 @@ const Desktop = new (class {
*/
addToListeners(module, event, callback, once, response = false) {
const self = this;
const eventName = response ? this.getResponseEventName(module, event) :
this.getEventName(module, event);
const eventName = response ? this.getResponseEventName(module, event) : this.getEventName(module, event);

function handler(...args) {
if (eventName in self.eventListeners) {
self.eventListeners[eventName].forEach(eventHandler => eventHandler(...args));
self.eventListeners[eventName].forEach((eventHandler) => eventHandler(...args));
}
if (eventName in self.onceEventListeners) {
self.onceEventListeners[eventName].forEach((eventHandler) => {
Expand Down Expand Up @@ -218,14 +219,13 @@ const Desktop = new (class {
const fetchId = this.fetchCallCounter;

return new Promise((resolve, reject) => {
this.once(module, `${event}_${fetchId}`,
(responseEvent, id, ...responseArgs) => {
if (id === fetchId) {
clearTimeout(this.fetchTimeoutTimers[fetchId]);
delete this.fetchTimeoutTimers[fetchId];
resolve(...responseArgs);
}
}, true);
this.once(module, `${event}_${fetchId}`, (responseEvent, id, ...responseArgs) => {
if (id === fetchId) {
clearTimeout(this.fetchTimeoutTimers[fetchId]);
delete this.fetchTimeoutTimers[fetchId];
resolve(...responseArgs);
}
}, true);
this.fetchTimeoutTimers[fetchId] = setTimeout(() => {
reject('timeout');
}, timeout);
Expand Down Expand Up @@ -290,20 +290,37 @@ const Desktop = new (class {
getResponseEventName(module, event) {
return `${this.getEventName(module, event)}___response`;
}
})();

asJSON() {
return {
electron: { webFrame: { getZoomFactor: () => 1 } },
fetch: (...args) => this.fetch(...args),
fetchAsset: (...args) => this.fetchAsset(...args),
fetchFile: (...args) => this.fetchFile(...args),
getAssetUrl: (...args) => this.getAssetUrl(...args),
getEventName: (...args) => this.getEventName(...args),
getFileUrl: (...args) => this.getFileUrl(...args),
on: (...args) => this.on(...args),
once: (...args) => this.once(...args),
removeAllListeners: (...args) => this.removeAllListeners(...args),
removeListener: (...args) => this.removeListener(...args),
respond: (...args) => this.respond(...args),
send: (...args) => this.send(...args),
sendGlobal: (...args) => this.sendGlobal(...args),
setDefaultFetchTimeout: (...args) => this.setDefaultFetchTimeout(...args)
};
}
})();

process.once('loaded', () => {
if (process.env.NODE_ENV === 'test') {
global.electronRequire = require;
global.process = process;
}

Desktop.electron = [];

exposedModules.forEach((module) => {
Desktop.electron[module] = require('electron')[module];
});

global.Desktop = Desktop;
// exposeInMainWorld support only plain object with methods declared on first level
contextBridge.exposeInMainWorld('Desktop', Desktop.asJSON());
Copy link
Author

@mjcctech mjcctech Nov 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exposing electron module webFrame cause Electron contextBridge recursion depth exceeded. Nested objects deeper than 1000 are not supported error. Now integration test pass because I fake this module in line 296 electron: { webFrame: { getZoomFactor: () => 1 } },

I don't know how to overcome this issue. I'm not using this functionality.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, the tests are green, so that is a good first step. The question is how much else is needed from the electron object there, or if we can clone the object with limited depth to fix the original issue.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, the tests are green, so that is a good first step.

Jan (@StorytellerCZ ) which other steps are needed to commit this to a RC branch so we can test it out?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will do an rc release for 3.2, if I get some time in the next few days.

If not, then ping me on Monday here:
https://www.youtube.com/watch?v=8s65DpKSVeQ

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@StorytellerCZ you are going to solve issue with exposing electron modules, right? Otherwise I propose to remove this functionality from meteor-desktop, make breaking change and put in release notes information about it.

Copy link

@a4xrbj1 a4xrbj1 Dec 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will do an rc release for 3.2, if I get some time in the next few days.

Hi @StorytellerCZ ,

can you please do a RC release?

Just got a notification from Snyk that there’s a vulnerability for Electron 11.5.0: https://security.snyk.io/vuln/SNYK-JS-ELECTRON-6097142

Thank you.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Published communitypackages:[email protected].
Published communitypackages:[email protected].
@meteor-community/[email protected] under the preview tag.

});