Skip to content

Commit

Permalink
Fixed asar issues in release builds (quickjs-emscripten, source-map, …
Browse files Browse the repository at this point in the history
…etc...)
  • Loading branch information
olegbl committed Jun 22, 2024
1 parent fb057c1 commit 49e6c53
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 55 deletions.
2 changes: 2 additions & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Mod Manager

- Fix linter
- Auto-updates (https://www.electron.build/auto-update)
- Mod config actions
- Typeahead config

Expand Down
14 changes: 12 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@
"appId": "com.lokhvitsky.D2RMM",
"artifactName": "${productName} ${version}.${ext}",
"asar": true,
"asarUnpack": "**\\*.{node,dll}",
"asarUnpack": [
"**\\*.{node,dll,wasm}",
"**\\node_modules\\@jitl\\quickjs-wasmfile-release-sync\\dist\\{index.js,emscripten-module.mjs,emscripten-module.wasm}"
],
"win": {
"target": [
"zip"
Expand All @@ -58,6 +61,13 @@
"filter": [
"**/*"
]
},
{
"from": "node_modules/source-map/lib",
"to": "app.asar.unpacked/dist/main",
"filter": [
"mappings.wasm"
]
}
],
"extraFiles": [
Expand Down Expand Up @@ -187,7 +197,7 @@
"@mui/lab": "^5.0.0-alpha.170",
"@mui/material": "^5.15.19",
"electron-debug": "^3.2.0",
"electron-log": "^4.4.4",
"electron-log": "^5.1.5",
"electron-updater": "^4.6.5",
"history": "^5.2.0",
"json5": "^2.2.0",
Expand Down
3 changes: 2 additions & 1 deletion release/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
"postinstall": "npm run electron-rebuild && npm run link-modules"
},
"dependencies": {
"@jitl/quickjs-wasmfile-release-sync": "^0.29.2",
"ffi-napi": "^4.0.3",
"json5": "^2.2.0",
"quickjs-emscripten": "^0.29.2",
"quickjs-emscripten-core": "^0.29.2",
"ref-napi": "^3.0.3",
"regedit": "^5.1.2",
"typescript": "^5.2.2"
Expand Down
36 changes: 2 additions & 34 deletions release/app/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,7 @@
resolved "https://registry.yarnpkg.com/@jitl/quickjs-ffi-types/-/quickjs-ffi-types-0.29.2.tgz#91aaa6be43471b5c8fc3a85f94582c86d345ba2e"
integrity sha512-069uQTiEla2PphXg6UpyyJ4QXHkTj3S9TeXgaMCd8NDYz3ODBw5U/rkg6fhuU8SMpoDrWjEzybmV5Mi2Pafb5w==

"@jitl/[email protected]":
version "0.29.2"
resolved "https://registry.yarnpkg.com/@jitl/quickjs-wasmfile-debug-asyncify/-/quickjs-wasmfile-debug-asyncify-0.29.2.tgz#ddf58d1ab90b94a70a73b93f95c4e17f16d0a2a9"
integrity sha512-YdRw2414pFkxzyyoJGv81Grbo9THp/5athDMKipaSBNNQvFE9FGRrgE9tt2DT2mhNnBx1kamtOGj0dX84Yy9bg==
dependencies:
"@jitl/quickjs-ffi-types" "0.29.2"

"@jitl/[email protected]":
version "0.29.2"
resolved "https://registry.yarnpkg.com/@jitl/quickjs-wasmfile-debug-sync/-/quickjs-wasmfile-debug-sync-0.29.2.tgz#b1a9c0f9371de2e8e67f8d025c0d9c9b7360f175"
integrity sha512-VgisubjyPMWEr44g+OU0QWGyIxu7VkApkLHMxdORX351cw22aLTJ+Z79DJ8IVrTWc7jh4CBPsaK71RBQDuVB7w==
dependencies:
"@jitl/quickjs-ffi-types" "0.29.2"

"@jitl/[email protected]":
version "0.29.2"
resolved "https://registry.yarnpkg.com/@jitl/quickjs-wasmfile-release-asyncify/-/quickjs-wasmfile-release-asyncify-0.29.2.tgz#51c23bfd93d56d9eaab47ee937838c91376b093a"
integrity sha512-sf3luCPr8wBVmGV6UV8Set+ie8wcO6mz5wMvDVO0b90UVCKfgnx65A1JfeA+zaSGoaFyTZ3sEpXSGJU+6qJmLw==
dependencies:
"@jitl/quickjs-ffi-types" "0.29.2"

"@jitl/[email protected]":
"@jitl/quickjs-wasmfile-release-sync@^0.29.2":
version "0.29.2"
resolved "https://registry.yarnpkg.com/@jitl/quickjs-wasmfile-release-sync/-/quickjs-wasmfile-release-sync-0.29.2.tgz#7a9a055739bfc6261203701a46e2c627cfabe6f2"
integrity sha512-UFIcbY3LxBRUjEqCHq3Oa6bgX5znt51V5NQck8L2US4u989ErasiMLUjmhq6UPC837Sjqu37letEK/ZpqlJ7aA==
Expand Down Expand Up @@ -132,24 +111,13 @@ node-gyp-build@^4.2.1:
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3"
integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==

[email protected]:
quickjs-emscripten-core@^0.29.2:
version "0.29.2"
resolved "https://registry.yarnpkg.com/quickjs-emscripten-core/-/quickjs-emscripten-core-0.29.2.tgz#ad9bef103fce7d8ba879510905824e33119a62f3"
integrity sha512-jEAiURW4jGqwO/fW01VwlWqa2G0AJxnN5FBy1xnVu8VIVhVhiaxUfCe+bHqS6zWzfjFm86HoO40lzpteusvyJA==
dependencies:
"@jitl/quickjs-ffi-types" "0.29.2"

quickjs-emscripten@^0.29.2:
version "0.29.2"
resolved "https://registry.yarnpkg.com/quickjs-emscripten/-/quickjs-emscripten-0.29.2.tgz#da6c7afb543cc5b4854eaca457778cfae5069f8b"
integrity sha512-SlvkvyZgarReu2nr4rkf+xz1vN0YDUz7sx4WHz8LFtK6RNg4/vzAGcFjE7nfHYBEbKrzfIWvKnMnxZkctQ898w==
dependencies:
"@jitl/quickjs-wasmfile-debug-asyncify" "0.29.2"
"@jitl/quickjs-wasmfile-debug-sync" "0.29.2"
"@jitl/quickjs-wasmfile-release-asyncify" "0.29.2"
"@jitl/quickjs-wasmfile-release-sync" "0.29.2"
quickjs-emscripten-core "0.29.2"

"readable-stream@>=1.0.33-1 <1.1.0-0":
version "1.0.34"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
Expand Down
23 changes: 11 additions & 12 deletions src/main/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
} from 'fs';
import json5 from 'json5';
import path from 'path';
import { Scope, getQuickJSSync } from 'quickjs-emscripten';
import { Scope } from 'quickjs-emscripten';
import ref from 'ref-napi';
import regedit from 'regedit';
import {
Expand All @@ -23,29 +23,23 @@ import {
SourceMapGenerator,
} from 'source-map';
import ts from 'typescript';
import type { ConsoleAPI } from 'bridge/ConsoleAPI';
import type { JSONData } from 'bridge/JSON';
import type { ModConfigValue } from 'bridge/ModConfigValue';
import type { TSVDataRow } from 'bridge/TSV';
import packageManifest from '../../release/app/package.json';
import { getConsoleAPI } from './ConsoleAPI';
import { InstallationRuntime } from './InstallationRuntime';
import { getModAPI } from './ModAPI';
import './asar.ts';
import { datamod } from './datamod';
import { getQuickJS } from './quickjs';

function notNull<TValue>(value: TValue | null | undefined): value is TValue {
return value !== null && value !== undefined;
}

let runtime: InstallationRuntime | null = null;

const console: ConsoleAPI = {
debug: (..._args: unknown[]): void => {},
log: (..._args: unknown[]): void => {},
warn: (..._args: unknown[]): void => {},
error: (..._args: unknown[]): void => {},
};

function getAppPath(): string {
return app.isPackaged
? path.join(process.resourcesPath, '../')
Expand Down Expand Up @@ -77,7 +71,7 @@ function getOutputRootPath(): string {

// we don't want mods doing any ../../.. shenanigans
function validatePathIsSafe(allowedRoot: string, absolutePath: string): string {
if (!absolutePath.startsWith(allowedRoot)) {
if (!path.resolve(absolutePath).startsWith(path.resolve(allowedRoot))) {
throw new Error(
`Path "${absolutePath}" points outside of allowed directory "${allowedRoot}".`
);
Expand Down Expand Up @@ -1095,11 +1089,12 @@ const config = JSON.parse(D2RMM.getConfigJSON());
if (error instanceof Error) {
console.error(`Mod encountered a compile error!\n${error.stack}`);
}
continue;
}
const scope = new Scope();
try {
console.debug(`Mod ${action.toLowerCase()}ing...`);
const vm = scope.manage(getQuickJSSync().newContext());
const vm = scope.manage(getQuickJS().newContext());
vm.setProp(vm.global, 'console', getConsoleAPI(vm, scope, console));
vm.setProp(vm.global, 'D2RMM', getModAPI(vm, scope, runtime));
scope.manage(vm.unwrapResult(vm.evalCode(code)));
Expand Down Expand Up @@ -1159,9 +1154,12 @@ export async function initBridgeAPI(mainWindow: BrowserWindow): Promise<void> {
});

// forward console messages to the renderer process
const nativeConsole = { ...console };
const consoleWrapper = { ...console };
const consoleMethods = ['debug', 'log', 'warn', 'error'] as const;
consoleMethods.forEach((level: typeof consoleMethods[number]) => {
console[level] = (...args) => {
consoleWrapper[level] = (...args) => {
nativeConsole[level](...args);
if (runtime?.isModInstalling() ?? false) {
mainWindow.webContents.send('console', [
level,
Expand All @@ -1172,6 +1170,7 @@ export async function initBridgeAPI(mainWindow: BrowserWindow): Promise<void> {
}
};
});
Object.assign(console, consoleWrapper);
}

function findBestMappingForLine(
Expand Down
33 changes: 33 additions & 0 deletions src/main/asar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { app } from 'electron';
import { existsSync } from 'fs';
import path from 'path';

type Method = (...args: string[]) => string;

function wrap(method: Method): Method {
return function (): string {
const result = method.call(path, ...arguments);

// .wasm modules cannot be shipped inside of app.asar
// so we ship them in app.asar.unpacked, but we need to
// adjust the file paths that they are loaded from
if (
result.endsWith('.wasm') &&
result.includes('app.asar') &&
!result.includes('app.asar.unpacked')
) {
const unpackedPath = result.replace(/app.asar/g, 'app.asar.unpacked');
if (existsSync(unpackedPath)) {
return unpackedPath;
}
}

return result;
};
}

if (app.isPackaged) {
path.resolve = wrap(path.resolve);
path.join = wrap(path.join);
path.normalize = wrap(path.normalize);
}
17 changes: 15 additions & 2 deletions src/main/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,25 @@
*/
import 'core-js/stable';
import { app, BrowserWindow, shell } from 'electron';
import log from 'electron-log/main';
import path from 'path';
import { getQuickJS } from 'quickjs-emscripten';
import 'regenerator-runtime/runtime';
import { initBridgeAPI } from './api';
import { initPreferences } from './preferences';
import { initQuickJS } from './quickjs';
import { resolveHtmlPath } from './util';

log.initialize();
log.transports.file.resolvePathFn = () =>
path.join(
app.isPackaged
? path.join(process.resourcesPath, '../')
: path.join(__dirname, '../../'),
'd2rmm.log'
);
Object.assign(console, log.functions);
console.log('electron-log initialized');

let mainWindow: BrowserWindow | null = null;
if (process.env.NODE_ENV === 'production') {
const sourceMapSupport = require('source-map-support');
Expand Down Expand Up @@ -72,7 +84,6 @@ const createWindow = async () => {
mainWindow.setTitle(`[D2RMM] Diablo II: Resurrected Mod Manager ${version}`);
mainWindow.removeMenu();

await getQuickJS();
await initBridgeAPI(mainWindow);

mainWindow.loadURL(resolveHtmlPath('index.html'));
Expand All @@ -97,6 +108,8 @@ const createWindow = async () => {
event.preventDefault();
shell.openExternal(url);
});

await initQuickJS();
};

app.on('window-all-closed', () => {
Expand Down
56 changes: 56 additions & 0 deletions src/main/quickjs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { app } from 'electron';
import { readFileSync } from 'fs';
import path from 'path';
import {
newQuickJSWASMModuleFromVariant,
QuickJSWASMModule,
newVariant,
} from 'quickjs-emscripten-core';
import releaseSyncVariant from '@jitl/quickjs-wasmfile-release-sync';

let loadedQuickJSWASMModule: QuickJSWASMModule | null;

export async function initQuickJS(): Promise<void> {
const modulePath = path.join(
process.resourcesPath,
'app.asar.unpacked/node_modules',
'@jitl/quickjs-wasmfile-release-sync/dist'
);

// issue: https://github.com/electron/asar/issues/249
// fix: https://github.com/electron/electron/pull/37535
// lots of blockers prevent upgrading electron & NodeJS versions :(
const variant = app.isPackaged
? newVariant(
{
...releaseSyncVariant,
importModuleLoader: () => {
const mjsSourceCode = readFileSync(
path.join(modulePath, 'emscripten-module.mjs')
)
.toString()
.replace(
/import.meta.url/g,
`"file:///${modulePath.replace(/\\/g, '/')}"`
)
.replace('export default ', '');
return eval(mjsSourceCode);
},
},
{
wasmBinary: readFileSync(
path.join(modulePath, 'emscripten-module.wasm')
),
}
)
: releaseSyncVariant;

loadedQuickJSWASMModule = await newQuickJSWASMModuleFromVariant(variant);
}

export function getQuickJS(): QuickJSWASMModule {
if (loadedQuickJSWASMModule == null) {
throw new Error('QuickJS module not loaded');
}
return loadedQuickJSWASMModule;
}
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4238,10 +4238,10 @@ electron-localshortcut@^3.1.0:
keyboardevent-from-electron-accelerator "^2.0.0"
keyboardevents-areequal "^0.2.1"

electron-log@^4.4.4:
version "4.4.5"
resolved "https://registry.yarnpkg.com/electron-log/-/electron-log-4.4.5.tgz#5fcfd0c2dc5fbda915ee0a9d802705dc57930786"
integrity sha512-Cfa2CKnwBhlUfIl/qr2GF5SCqfoA9yPBqTJ6/wPs+PEn36M2+EZ3RpGSaOhYQ1BZpolL1CWyeu3gMG8epLl3Ng==
electron-log@^5.1.5:
version "5.1.5"
resolved "https://registry.yarnpkg.com/electron-log/-/electron-log-5.1.5.tgz#70d5051fc5ab7669b2592f53f72034867269c96e"
integrity sha512-vuq10faUAxRbILgQx7yHoMObKZDEfj7hMSZrJPsVrDNeCpV/HN11dU7QuY4UDUe055pzBxhSCB3m0+6D3Aktjw==

electron-notarize@^1.1.1:
version "1.1.1"
Expand Down

0 comments on commit 49e6c53

Please sign in to comment.