chore: restore deprecate as an internal module (#40124)

* Revert "refactor: don't expose deprecate as an internal module (#35311)"

This reverts commit 8424779906.

* check crashed event warnings
This commit is contained in:
Milan Burda 2023-10-09 01:55:16 +02:00 committed by GitHub
parent 8b8fbd0408
commit 737e3de3fa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 106 additions and 27 deletions

View file

@ -142,6 +142,7 @@ auto_filenames = {
] ]
sandbox_bundle_deps = [ sandbox_bundle_deps = [
"lib/common/api/deprecate.ts",
"lib/common/api/native-image.ts", "lib/common/api/native-image.ts",
"lib/common/define-properties.ts", "lib/common/define-properties.ts",
"lib/common/ipc-messages.ts", "lib/common/ipc-messages.ts",
@ -247,11 +248,11 @@ auto_filenames = {
"lib/browser/parse-features-string.ts", "lib/browser/parse-features-string.ts",
"lib/browser/rpc-server.ts", "lib/browser/rpc-server.ts",
"lib/browser/web-view-events.ts", "lib/browser/web-view-events.ts",
"lib/common/api/deprecate.ts",
"lib/common/api/module-list.ts", "lib/common/api/module-list.ts",
"lib/common/api/native-image.ts", "lib/common/api/native-image.ts",
"lib/common/api/shell.ts", "lib/common/api/shell.ts",
"lib/common/define-properties.ts", "lib/common/define-properties.ts",
"lib/common/deprecate.ts",
"lib/common/init.ts", "lib/common/init.ts",
"lib/common/ipc-messages.ts", "lib/common/ipc-messages.ts",
"lib/common/reset-search-paths.ts", "lib/common/reset-search-paths.ts",
@ -265,6 +266,7 @@ auto_filenames = {
] ]
renderer_bundle_deps = [ renderer_bundle_deps = [
"lib/common/api/deprecate.ts",
"lib/common/api/module-list.ts", "lib/common/api/module-list.ts",
"lib/common/api/native-image.ts", "lib/common/api/native-image.ts",
"lib/common/api/shell.ts", "lib/common/api/shell.ts",
@ -303,6 +305,7 @@ auto_filenames = {
] ]
worker_bundle_deps = [ worker_bundle_deps = [
"lib/common/api/deprecate.ts",
"lib/common/api/module-list.ts", "lib/common/api/module-list.ts",
"lib/common/api/native-image.ts", "lib/common/api/native-image.ts",
"lib/common/api/shell.ts", "lib/common/api/shell.ts",

View file

@ -1,7 +1,6 @@
import * as fs from 'fs'; import * as fs from 'fs';
import { Menu } from 'electron/main'; import { Menu, deprecate } from 'electron/main';
import * as deprecate from '@electron/internal/common/deprecate';
const bindings = process._linkedBinding('electron_browser_app'); const bindings = process._linkedBinding('electron_browser_app');
const commandLine = process._linkedBinding('electron_common_command_line'); const commandLine = process._linkedBinding('electron_common_command_line');

View file

@ -1,5 +1,4 @@
import { app } from 'electron/main'; import { app, deprecate } from 'electron/main';
import * as deprecate from '@electron/internal/common/deprecate';
const binding = process._linkedBinding('electron_browser_crash_reporter'); const binding = process._linkedBinding('electron_browser_crash_reporter');

View file

@ -1,4 +1,4 @@
import { app, ipcMain, session, webFrameMain } from 'electron/main'; import { app, ipcMain, session, webFrameMain, deprecate } from 'electron/main';
import type { BrowserWindowConstructorOptions, LoadURLOptions } from 'electron/main'; import type { BrowserWindowConstructorOptions, LoadURLOptions } from 'electron/main';
import * as url from 'url'; import * as url from 'url';
@ -10,7 +10,6 @@ import * as ipcMainUtils from '@electron/internal/browser/ipc-main-internal-util
import { MessagePortMain } from '@electron/internal/browser/message-port-main'; import { MessagePortMain } from '@electron/internal/browser/message-port-main';
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages'; import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
import { IpcMainImpl } from '@electron/internal/browser/ipc-main-impl'; import { IpcMainImpl } from '@electron/internal/browser/ipc-main-impl';
import * as deprecate from '@electron/internal/common/deprecate';
// session is not used here, the purpose is to make sure session is initialized // session is not used here, the purpose is to make sure session is initialized
// before the webContents module. // before the webContents module.

View file

@ -2,13 +2,13 @@ type DeprecationHandler = (message: string) => void;
let deprecationHandler: DeprecationHandler | null = null; let deprecationHandler: DeprecationHandler | null = null;
export function warnOnce (oldName: string, newName?: string) { function warnOnce (oldName: string, newName?: string) {
return warnOnceMessage(newName return warnOnceMessage(newName
? `'${oldName}' is deprecated and will be removed. Please use '${newName}' instead.` ? `'${oldName}' is deprecated and will be removed. Please use '${newName}' instead.`
: `'${oldName}' is deprecated and will be removed.`); : `'${oldName}' is deprecated and will be removed.`);
} }
export function warnOnceMessage (msg: string) { function warnOnceMessage (msg: string) {
let warned = false; let warned = false;
return () => { return () => {
if (!warned && !process.noDeprecation) { if (!warned && !process.noDeprecation) {
@ -18,21 +18,21 @@ export function warnOnceMessage (msg: string) {
}; };
} }
export function setHandler (handler: DeprecationHandler | null): void { function setHandler (handler: DeprecationHandler | null): void {
deprecationHandler = handler; deprecationHandler = handler;
} }
export function getHandler (): DeprecationHandler | null { function getHandler (): DeprecationHandler | null {
return deprecationHandler; return deprecationHandler;
} }
export function warn (oldName: string, newName: string): void { function warn (oldName: string, newName: string): void {
if (!process.noDeprecation) { if (!process.noDeprecation) {
log(`'${oldName}' is deprecated. Use '${newName}' instead.`); log(`'${oldName}' is deprecated. Use '${newName}' instead.`);
} }
} }
export function log (message: string): void { function log (message: string): void {
if (typeof deprecationHandler === 'function') { if (typeof deprecationHandler === 'function') {
deprecationHandler(message); deprecationHandler(message);
} else if (process.throwDeprecation) { } else if (process.throwDeprecation) {
@ -45,7 +45,7 @@ export function log (message: string): void {
} }
// remove a function with no replacement // remove a function with no replacement
export function removeFunction<T extends Function> (fn: T, removedName: string): T { function removeFunction<T extends Function> (fn: T, removedName: string): T {
if (!fn) { throw new Error(`'${removedName} function' is invalid or does not exist.`); } if (!fn) { throw new Error(`'${removedName} function' is invalid or does not exist.`); }
// wrap the deprecated function to warn user // wrap the deprecated function to warn user
@ -57,7 +57,7 @@ export function removeFunction<T extends Function> (fn: T, removedName: string):
} }
// change the name of a function // change the name of a function
export function renameFunction<T extends Function> (fn: T, newName: string): T { function renameFunction<T extends Function> (fn: T, newName: string): T {
const warn = warnOnce(`${fn.name} function`, `${newName} function`); const warn = warnOnce(`${fn.name} function`, `${newName} function`);
return function (this: any) { return function (this: any) {
warn(); warn();
@ -66,7 +66,7 @@ export function renameFunction<T extends Function> (fn: T, newName: string): T {
} }
// change the name of an event // change the name of an event
export function event (emitter: NodeJS.EventEmitter, oldName: string, newName: string, transformer: (...args: any[]) => any[] | undefined = (...args) => args) { function event (emitter: NodeJS.EventEmitter, oldName: string, newName: string, transformer: (...args: any[]) => any[] | undefined = (...args) => args) {
const warn = newName.startsWith('-') /* internal event */ const warn = newName.startsWith('-') /* internal event */
? warnOnce(`${oldName} event`) ? warnOnce(`${oldName} event`)
: warnOnce(`${oldName} event`, `${newName} event`); : warnOnce(`${oldName} event`, `${newName} event`);
@ -82,7 +82,7 @@ export function event (emitter: NodeJS.EventEmitter, oldName: string, newName: s
} }
// remove a property with no replacement // remove a property with no replacement
export function removeProperty<T, K extends (keyof T & string)>(object: T, removedName: K, onlyForValues?: any[]): T { function removeProperty<T extends Object, K extends (keyof T & string)>(object: T, removedName: K, onlyForValues?: any[]): T {
// if the property's already been removed, warn about it // if the property's already been removed, warn about it
// eslint-disable-next-line no-proto // eslint-disable-next-line no-proto
const info = Object.getOwnPropertyDescriptor((object as any).__proto__, removedName); const info = Object.getOwnPropertyDescriptor((object as any).__proto__, removedName);
@ -113,7 +113,7 @@ export function removeProperty<T, K extends (keyof T & string)>(object: T, remov
} }
// change the name of a property // change the name of a property
export function renameProperty<T extends Object, K extends (keyof T & string)>(object: T, oldName: string, newName: K): T { function renameProperty<T extends Object, K extends (keyof T & string)>(object: T, oldName: string, newName: K): T {
const warn = warnOnce(oldName, newName); const warn = warnOnce(oldName, newName);
// if the new property isn't there yet, // if the new property isn't there yet,
@ -137,10 +137,27 @@ export function renameProperty<T extends Object, K extends (keyof T & string)>(o
}); });
} }
export function moveAPI<T extends Function> (fn: T, oldUsage: string, newUsage: string): T { function moveAPI<T extends Function> (fn: T, oldUsage: string, newUsage: string): T {
const warn = warnOnce(oldUsage, newUsage); const warn = warnOnce(oldUsage, newUsage);
return function (this: any) { return function (this: any) {
warn(); warn();
return fn.apply(this, arguments); return fn.apply(this, arguments);
} as unknown as typeof fn; } as unknown as typeof fn;
} }
const deprecate: ElectronInternal.DeprecationUtil = {
warnOnce,
warnOnceMessage,
setHandler,
getHandler,
warn,
log,
removeFunction,
renameFunction,
event,
removeProperty,
renameProperty,
moveAPI
};
export default deprecate;

View file

@ -1,5 +1,7 @@
// Common modules, please sort alphabetically // Common modules, please sort alphabetically
export const commonModuleList: ElectronInternal.ModuleEntry[] = [ export const commonModuleList: ElectronInternal.ModuleEntry[] = [
{ name: 'nativeImage', loader: () => require('./native-image') }, { name: 'nativeImage', loader: () => require('./native-image') },
{ name: 'shell', loader: () => require('./shell') } { name: 'shell', loader: () => require('./shell') },
// The internal modules, invisible unless you know their names.
{ name: 'deprecate', loader: () => require('./deprecate'), private: true }
]; ];

View file

@ -9,7 +9,7 @@ export function defineProperties (targetExports: Object, moduleList: ElectronInt
const descriptors: PropertyDescriptorMap = {}; const descriptors: PropertyDescriptorMap = {};
for (const module of moduleList) { for (const module of moduleList) {
descriptors[module.name] = { descriptors[module.name] = {
enumerable: true, enumerable: !module.private,
get: handleESModule(module.loader) get: handleESModule(module.loader)
}; };
} }

View file

@ -18,5 +18,11 @@ export const moduleList: ElectronInternal.ModuleEntry[] = [
{ {
name: 'webFrame', name: 'webFrame',
loader: () => require('@electron/internal/renderer/api/web-frame') loader: () => require('@electron/internal/renderer/api/web-frame')
},
// The internal modules, invisible unless you know their names.
{
name: 'deprecate',
loader: () => require('@electron/internal/common/api/deprecate'),
private: true
} }
]; ];

View file

@ -6,7 +6,7 @@ import * as net from 'node:net';
import * as fs from 'fs-extra'; import * as fs from 'fs-extra';
import * as path from 'node:path'; import * as path from 'node:path';
import { promisify } from 'node:util'; import { promisify } from 'node:util';
import { app, BrowserWindow, Menu, session, net as electronNet, WebContents } from 'electron/main'; import { app, BrowserWindow, Menu, session, net as electronNet, WebContents, deprecate } from 'electron/main';
import { closeWindow, closeAllWindows } from './lib/window-helpers'; import { closeWindow, closeAllWindows } from './lib/window-helpers';
import { ifdescribe, ifit, listen, waitUntil } from './lib/spec-helpers'; import { ifdescribe, ifit, listen, waitUntil } from './lib/spec-helpers';
import { once } from 'node:events'; import { once } from 'node:events';
@ -492,7 +492,10 @@ describe('app module', () => {
describe('BrowserWindow events', () => { describe('BrowserWindow events', () => {
let w: BrowserWindow = null as any; let w: BrowserWindow = null as any;
afterEach(() => closeWindow(w).then(() => { w = null as any; })); afterEach(() => {
deprecate.setHandler(null);
closeWindow(w).then(() => { w = null as any; });
});
it('should emit browser-window-focus event when window is focused', async () => { it('should emit browser-window-focus event when window is focused', async () => {
const emitted = once(app, 'browser-window-focus') as Promise<[any, BrowserWindow]>; const emitted = once(app, 'browser-window-focus') as Promise<[any, BrowserWindow]>;
@ -535,11 +538,16 @@ describe('app module', () => {
}); });
await w.loadURL('about:blank'); await w.loadURL('about:blank');
const emitted = once(app, 'renderer-process-crashed') as Promise<[any, WebContents]>; const messages: string[] = [];
deprecate.setHandler(message => messages.push(message));
const emitted = once(app, 'renderer-process-crashed') as Promise<[any, WebContents, boolean]>;
w.webContents.executeJavaScript('process.crash()'); w.webContents.executeJavaScript('process.crash()');
const [, webContents] = await emitted; const [, webContents, killed] = await emitted;
expect(webContents).to.equal(w.webContents); expect(webContents).to.equal(w.webContents);
expect(killed).to.be.false();
expect(messages).to.deep.equal(['\'renderer-process-crashed event\' is deprecated and will be removed. Please use \'render-process-gone event\' instead.']);
}); });
// FIXME: re-enable this test on win32. // FIXME: re-enable this test on win32.

View file

@ -3,7 +3,7 @@ import { AddressInfo } from 'node:net';
import * as path from 'node:path'; import * as path from 'node:path';
import * as fs from 'node:fs'; import * as fs from 'node:fs';
import * as http from 'node:http'; import * as http from 'node:http';
import { BrowserWindow, ipcMain, webContents, session, app, BrowserView, WebContents } from 'electron/main'; import { BrowserWindow, ipcMain, webContents, session, app, BrowserView, WebContents, deprecate } from 'electron/main';
import { closeAllWindows } from './lib/window-helpers'; import { closeAllWindows } from './lib/window-helpers';
import { ifdescribe, defer, waitUntil, listen, ifit } from './lib/spec-helpers'; import { ifdescribe, defer, waitUntil, listen, ifit } from './lib/spec-helpers';
import { once } from 'node:events'; import { once } from 'node:events';
@ -2331,6 +2331,8 @@ describe('webContents module', () => {
}); });
describe('crashed event', () => { describe('crashed event', () => {
afterEach(() => deprecate.setHandler(null));
it('does not crash main process when destroying WebContents in it', async () => { it('does not crash main process when destroying WebContents in it', async () => {
const contents = (webContents as typeof ElectronInternal.WebContents).create({ nodeIntegration: true }); const contents = (webContents as typeof ElectronInternal.WebContents).create({ nodeIntegration: true });
const crashEvent = once(contents, 'render-process-gone'); const crashEvent = once(contents, 'render-process-gone');
@ -2339,6 +2341,21 @@ describe('webContents module', () => {
await crashEvent; await crashEvent;
contents.destroy(); contents.destroy();
}); });
it('logs a warning', async () => {
const contents = (webContents as typeof ElectronInternal.WebContents).create({ nodeIntegration: true });
await contents.loadURL('about:blank');
const messages: string[] = [];
deprecate.setHandler(message => messages.push(message));
const crashEvent = once(contents, 'crashed');
contents.forcefullyCrashRenderer();
const [, killed] = await crashEvent;
expect(killed).to.be.a('boolean');
expect(messages).to.deep.equal(['\'crashed event\' is deprecated and will be removed. Please use \'render-process-gone event\' instead.']);
});
}); });
describe('context-menu event', () => { describe('context-menu event', () => {

View file

@ -1,5 +1,5 @@
import { expect } from 'chai'; import { expect } from 'chai';
import * as deprecate from '../lib/common/deprecate'; import { deprecate } from 'electron/main';
describe('deprecate', () => { describe('deprecate', () => {
let throwing: boolean; let throwing: boolean;

View file

@ -155,6 +155,18 @@ declare namespace Electron {
_replyChannel: ReplyChannel; _replyChannel: ReplyChannel;
} }
namespace Common {
const deprecate: ElectronInternal.DeprecationUtil;
}
namespace Main {
const deprecate: ElectronInternal.DeprecationUtil;
}
namespace Renderer {
const deprecate: ElectronInternal.DeprecationUtil;
}
class View {} class View {}
// Experimental views API // Experimental views API
@ -200,6 +212,22 @@ declare namespace Electron {
} }
declare namespace ElectronInternal { declare namespace ElectronInternal {
type DeprecationHandler = (message: string) => void;
interface DeprecationUtil {
warnOnce(oldName: string, newName?: string): () => void;
warnOnceMessage(msg: string): () => void;
setHandler(handler: DeprecationHandler | null): void;
getHandler(): DeprecationHandler | null;
warn(oldName: string, newName: string): void;
log(message: string): void;
removeFunction<T extends Function>(fn: T, removedName: string): T;
renameFunction<T extends Function>(fn: T, newName: string): T;
event(emitter: NodeJS.EventEmitter, oldName: string, newName: string, transformer?: (...args: any[]) => any[] | undefined): void;
removeProperty<T extends Object, K extends (keyof T & string)>(object: T, propertyName: K, onlyForValues?: any[]): T;
renameProperty<T extends Object, K extends (keyof T & string)>(object: T, oldName: string, newName: K): T;
moveAPI<T extends Function>(fn: T, oldUsage: string, newUsage: string): T;
}
interface DesktopCapturer { interface DesktopCapturer {
startHandling(captureWindow: boolean, captureScreen: boolean, thumbnailSize: Electron.Size, fetchWindowIcons: boolean): void; startHandling(captureWindow: boolean, captureScreen: boolean, thumbnailSize: Electron.Size, fetchWindowIcons: boolean): void;
_onerror?: (error: string) => void; _onerror?: (error: string) => void;
@ -264,6 +292,7 @@ declare namespace ElectronInternal {
interface ModuleEntry { interface ModuleEntry {
name: string; name: string;
loader: ModuleLoader; loader: ModuleLoader;
private?: boolean;
} }
interface UtilityProcessWrapper extends NodeJS.EventEmitter { interface UtilityProcessWrapper extends NodeJS.EventEmitter {