英文:
Can't use any methods of an istance of a third-party modules [chess.js] (ELECTRON - preload.js & render.js problem)
问题
今天我面临了这个问题:我试图创建一个使用chess.js模块的国际象棋应用程序(使用Electron),但问题迅速显现出来了... 我需要在我的render.js文件中使用chess.js提供的所有方法/功能,比如chess.move(),chess.fen()等等... 但是在将sandbox: false(在webPreferences中)设置为false并在我的preload脚本**(preload.js)**中编写以下内容之后:
const { contextBridge, ipcRenderer} = require('electron')
contextBridge.exposeInMainWorld(
'electron',
{
//其他代码
getChess : () => {
const {Chess} = require('chess.js');
return chess = new Chess;
}
}
)
我无法使用任何方法(为了更清楚,我无法在我的render脚本中使用Chess的"chess"实例,我可以记录这个,它会显示obj(如预期的那样))
这是我的render脚本**(render.js)**:
//通过preload.js获取Chess
const chess = window.electron.getChess();
//✅ 正常工作(显示chess对象)
console.log(chess)
//❌ 不工作(示例 Uncaught TypeError: chess.move is not a function)
chess.move('e42')
chess.inCheck()
chess.isAttacked()
chess.load()
chess.clear()
chess.board()
chess.fen()
chess.png()
//. . .
可能是一个愚蠢的问题,但对我来说似乎很难理解。
chess.js有很多方法,如.fen、.move、.load...我需要一种方法来包含所有这些方法在我的render中。
我不想设置nodeIntegration: true,因为出于安全原因。
不知道是否有帮助,但这是我的main.js文件:
const { app, BrowserWindow, Menu, ipcMain} = require('electron')
const path = require('path')
const ipc = ipcMain
Menu.setApplicationMenu(false)
const createWindow = () => {
const win = new BrowserWindow({
width : 1500,
height : 900,
resizable: false,
titleBarStyle: 'hidden',
frame: false,
webPreferences: {
nodeIntegration: false, // 在Electron v5之后是默认值
contextIsolation: true, // 保护免受原型污染
enableRemoteModule: false, // 关闭远程
devTools: false,
sandbox: false,
preload: path.join(__dirname, 'preload.js'),
}
})
//win.webContents.openDevTools()
win.loadFile("src/index.html");
ipc.on('closeAPP', () => {
win.close()
})
ipc.on('minimizeAPP', () => {
win.minimize()
})
ipc.on('maximizeAPP', () => {
win.maximize()
})
}
app.whenReady().then( () => {
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
有办法使用所有这些方法吗?
英文:
Today i faced this problem: i was trying to create a chessboard app (with Electron) using the chess.js modules and the problems showed quickly... I need to use in my render.js file all methods/features that chess.js offers, such as chess.move(), chess.fen() and so on... But after setting sandbox: false (in webPreferences) and writing this in my preload script (preload.js):
const { contextBridge, ipcRenderer} = require('electron')
contextBridge.exposeInMainWorld(
'electron',
{
//other code
getChess : () => {
const {Chess} = require('chess.js');
return chess = new Chess;
}
}
)
i am unable to use any the methods (to make things more clearer, i am enable to use the "chess" istance of Chess in my render script, i can log this, and it will show the obj (as expected))
this is my render script (render.js):
//get Chess through preload.js
const chess = window.electron.getChess();
//✅ Working (showing the chess obj)
console.log(chess)
//❌ Not Working (example Uncaught TypeError: chess.move is not a function)
chess.move('e42')
chess.inCheck()
chess.isAttacked()
chess.load()
chess.clear()
chess.board()
chess.fen()
chess.png()
//. . .
Probably is something stupid to ask, but it seems to me hard to get through.
chess.js have a lot of methods .fen, .move, .load ... i need a way to include all to my render.
I don't wanna set nodeIntegration: true due to security reason.
idk if it will help but here is my main.js file :
const { app, BrowserWindow, Menu, ipcMain} = require('electron')
const path = require('path')
const ipc = ipcMain
Menu.setApplicationMenu(false)
const createWindow = () => {
const win = new BrowserWindow({
width : 1500,
height : 900,
resizable: false,
titleBarStyle: 'hidden',
frame: false,
webPreferences: {
nodeIntegration: false, // is default value after Electron v5
contextIsolation: true, // protect against prototype pollution
enableRemoteModule: false, // turn off remote
devTools: false,
sandbox: false,
preload: path.join(__dirname, 'preload.js'),
}
})
//win.webContents.openDevTools()
win.loadFile("src/index.html");
ipc.on('closeAPP', () => {
win.close()
})
ipc.on('minimizeAPP', () => {
win.minimize()
})
ipc.on('maximizeAPP', () => {
win.maximize()
})
}
app.whenReady().then( () => {
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
There is a way to use all the methods ?
答案1
得分: 1
这是设计如此。Electron 不支持,据说是出于安全原因,通过 contextBridge
发送“自定义类”(根据文档)并且删除除 Object
之外的对象的所有原型修改或原型。
这是因为你应该仅公开一些你确信不会对渲染进程造成伤害的函数,并且将所有处理都放在 preload.js
(不建议)或主进程中,并通过 IPC 传递值。
请注意,后者对于非标准的 Object
也不起作用,因此最好将你需要的 Chess
对象存储在主进程中,在那里进行操作,并仅传递给渲染进程所需的值(例如显示)。如何最好地完成这个任务在Electron 的 IPC 教程中有详细说明。
英文:
This is by design. Electron does not support, supposedly for security reasons, sending "custom classes" over the contextBridge
(as per the documentation) and drops all prototype modifications or prototypes of objects other than Object
itself.
This is because you're expected to expose only certain functions of which you're sure they cannot do harm to the renderer process and instead do all processing either in preload.js
(not recommended) or in the main process and pass values via IPC.
Mind that the latter will also not work for non-standard Object
s, thus it would be best to store the Chess
objects you'll need in the main process, manipulate them there, and only pass the values required for (ex.) display to the renderer process. How this is done best is explained in Electron's IPC tutorial.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论