Browse Source

fix: self.module.paths not working in web workers (#30014)

* fix: global.module.paths in workers

* spec: add a regression test

Co-authored-by: Shelley Vohr <[email protected]>
trop[bot] 3 years ago
parent
commit
a32c39955e

+ 9 - 0
lib/worker/init.ts

@@ -12,6 +12,9 @@ require('../common/reset-search-paths');
 // Import common settings.
 require('@electron/internal/common/init');
 
+// Process command line arguments.
+const { hasSwitch, getSwitchValue } = process._linkedBinding('electron_common_command_line');
+
 // Export node bindings to global.
 const { makeRequireFunction } = __non_webpack_require__('internal/modules/cjs/helpers') // eslint-disable-line
 global.module = new Module('electron/js2c/worker_init');
@@ -32,4 +35,10 @@ if (self.location.protocol === 'file:') {
   // For backwards compatibility we fake these two paths here
   global.__filename = path.join(process.resourcesPath, 'electron.asar', 'worker', 'init.js');
   global.__dirname = path.join(process.resourcesPath, 'electron.asar', 'worker');
+
+  const appPath = hasSwitch('app-path') ? getSwitchValue('app-path') : null;
+  if (appPath) {
+    // Search for module under the app directory.
+    global.module.paths = Module._nodeModulePaths(appPath);
+  }
 }

+ 20 - 0
spec-main/chromium-spec.ts

@@ -682,6 +682,26 @@ describe('chromium features', () => {
     });
   });
 
+  describe('web workers', () => {
+    let appProcess: ChildProcess.ChildProcessWithoutNullStreams | undefined;
+
+    afterEach(() => {
+      if (appProcess && !appProcess.killed) {
+        appProcess.kill();
+        appProcess = undefined;
+      }
+    });
+
+    it('Worker with nodeIntegrationInWorker has access to self.module.paths', async () => {
+      const appPath = path.join(__dirname, 'fixtures', 'apps', 'self-module-paths');
+
+      appProcess = ChildProcess.spawn(process.execPath, [appPath]);
+
+      const [code] = await emittedOnce(appProcess, 'exit');
+      expect(code).to.equal(0);
+    });
+  });
+
   describe('form submit', () => {
     let server: http.Server;
     let serverUrl: string;

+ 7 - 0
spec-main/fixtures/apps/self-module-paths/index.html

@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+  <body>
+    <h1>Hello World!</h1>
+    <script src="./renderer.js"></script>
+  </body>
+</html>

+ 34 - 0
spec-main/fixtures/apps/self-module-paths/main.js

@@ -0,0 +1,34 @@
+// Modules to control application life and create native browser window
+const { app, BrowserWindow, ipcMain } = require('electron');
+const path = require('path');
+
+function createWindow () {
+  const mainWindow = new BrowserWindow({
+    width: 800,
+    height: 600,
+    show: false,
+    webPreferences: {
+      nodeIntegration: true,
+      nodeIntegrationInWorker: true,
+      contextIsolation: false
+    }
+  });
+
+  mainWindow.loadFile('index.html');
+}
+
+ipcMain.handle('module-paths', (e, success) => {
+  process.exit(success ? 0 : 1);
+});
+
+app.whenReady().then(() => {
+  createWindow();
+
+  app.on('activate', function () {
+    if (BrowserWindow.getAllWindows().length === 0) createWindow();
+  });
+});
+
+app.on('window-all-closed', function () {
+  if (process.platform !== 'darwin') app.quit();
+});

+ 4 - 0
spec-main/fixtures/apps/self-module-paths/package.json

@@ -0,0 +1,4 @@
+{
+  "name": "electron-test-self-module-paths",
+  "main": "main.js"
+}

+ 12 - 0
spec-main/fixtures/apps/self-module-paths/renderer.js

@@ -0,0 +1,12 @@
+const { ipcRenderer } = require('electron');
+
+const worker = new Worker('worker.js');
+
+worker.onmessage = (event) => {
+  const workerPaths = event.data.sort().toString();
+  const rendererPaths = self.module.paths.sort().toString();
+  const validModulePaths = workerPaths === rendererPaths && workerPaths !== 0;
+
+  ipcRenderer.invoke('module-paths', validModulePaths);
+  worker.terminate();
+};

+ 1 - 0
spec-main/fixtures/apps/self-module-paths/worker.js

@@ -0,0 +1 @@
+self.postMessage(self.module.paths);