First pass polyfill

This commit is contained in:
2022-09-05 23:58:16 -04:00
parent 9e4f609cbe
commit c87b096459
25 changed files with 893 additions and 223 deletions
+28
View File
@@ -0,0 +1,28 @@
const crypto = (() => {
let cache = null;
return () => {
if (cache) return cache;
return cache = __non_webpack_require__("crypto");
};
})();
export function createHash(type) {
const hash = crypto().createHash(type);
const ctx = {
update(data) {
hash.update(data);
return ctx;
},
digest(encoding) {return hash.digest(encoding);}
};
return ctx;
}
export function randomBytes(length) {
return crypto().randomBytes(length);
}
+13
View File
@@ -0,0 +1,13 @@
import {ipcRenderer as IPC, shell} from "electron";
export const ipcRenderer = {
send: IPC.send.bind(IPC),
sendToHost: IPC.sendToHost.bind(IPC),
sendTo: IPC.sendTo.bind(IPC),
sendSync: IPC.sendSync.bind(IPC),
invoke: IPC.invoke.bind(IPC),
on: IPC.on.bind(IPC),
off: IPC.off.bind(IPC)
};
export {shell};
+73
View File
@@ -0,0 +1,73 @@
import * as fs from "fs";
import cloneObject from "common/clone";
import Logger from "common/logger";
export function readFile(path, options = "utf8") {
return fs.readFileSync(path, options);
}
export function writeFile(path, content, options) {
if (content instanceof Uint8Array) {
content = Buffer.from(content);
}
const doWriteFile = options?.originalFs ? __non_webpack_require__("original-fs").writeFileSync : fs.writeFileSync;
return doWriteFile(path, content, options);
}
export function readDirectory(path, options) {
return fs.readdirSync(path, options);
}
export function createDirectory(path, options) {
return fs.mkdirSync(path, options);
}
export function deleteDirectory(path, options) {
fs.rmdirSync(path, options);
}
export function exists(path) {
return fs.existsSync(path);
}
export function getRealPath(path, options) {
return fs.realpathSync(path, options);
}
export function rename(oldPath, newPath) {
return fs.renameSync(oldPath, newPath);
}
export function createWriteStream(path, options) {
return cloneObject(fs.createWriteStream(path, options));
}
export function watch(path, options, callback) {
const watcher = fs.watch(path, options, (event, filename) => {
try {
callback(event, filename);
}
catch (error) {
Logger.stacktrace("filesystem", "Failed to watch path", error);
}
});
return {
close: () => {
watcher.close();
}
};
}
export function getStats(path, options) {
const stats = fs.statSync(path, options);
return {
...stats,
isFile: stats.isFile.bind(stats),
isDirectory: stats.isDirectory.bind(stats),
isSymbolicLink: stats.isSymbolicLink.bind(stats)
};
}
+91
View File
@@ -0,0 +1,91 @@
import Logger from "common/logger";
let request;
const req = function (url, options, callback) {
if (!request) request = __non_webpack_require__("request");
return request(url, options, (error, res, body) => {
try {
Reflect.apply(callback, null, [error, res, body]);
}
catch (err) {
Logger.stacktrace("https", "Failed request", err);
}
});
};
export const get = function (url, options, callback) {
if (!request) request = __non_webpack_require__("request");
return request.get(url, options, (error, res, body) => {
try {
Reflect.apply(callback, null, [error, res, body]);
}
catch (err) {
Logger.stacktrace("https", "Failed get request", err);
}
});
};
export const put = function (url, options, callback) {
if (!request) request = __non_webpack_require__("request");
return request.put(url, options, (error, res, body) => {
try {
Reflect.apply(callback, null, [error, res, body]);
}
catch (err) {
Logger.stacktrace("https", "Failed put request", err);
}
});
};
export const post = function (url, options, callback) {
if (!request) request = __non_webpack_require__("request");
return request.post(url, options, (error, res, body) => {
try {
Reflect.apply(callback, null, [error, res, body]);
}
catch (err) {
Logger.stacktrace("https", "Failed post request", err);
}
});
};
const del = function (url, options, callback) {
if (!request) request = __non_webpack_require__("request");
return request.delete(url, options, (error, res, body) => {
try {
Reflect.apply(callback, null, [error, res, body]);
}
catch (err) {
Logger.stacktrace("https", "Failed delete request", err);
}
});
};
const head = function (url, options, callback) {
if (!request) request = __non_webpack_require__("request");
return request.head(url, options, (error, res, body) => {
try {
Reflect.apply(callback, null, [error, res, body]);
}
catch (err) {
Logger.stacktrace("https", "Failed head request", err);
}
});
};
export default req;
Object.assign(req, {
get,
put,
post,
head,
delete: del // eslint-disable-line quote-props
});
+14
View File
@@ -0,0 +1,14 @@
import path from "path";
import Module from "module";
Module.globalPaths.push(path.resolve(process.env.DISCORD_APP_PATH, "..", "app.asar", "node_modules"));
export * as filesystem from "./filesystem";
export * as https from "./https";
export * as electron from "./electron";
export * as crypto from "./crypto";
// We can expose that without any issues.
export * as path from "path";
export * as net from "net"; // TODO: evaluate need and create wrapper
export * as os from "os";
+12 -56
View File
@@ -1,59 +1,15 @@
const Module = require("module");
const path = require("path");
const electron = require("electron");
const NodeEvents = require("events");
import {contextBridge} from "electron";
import newProcess from "./process";
import * as BdApi from "./api";
import init from "./init";
const cloneObject = function (target, newObject = {}, keys) {
if (!Array.isArray(keys)) keys = Object.keys(Object.getOwnPropertyDescriptors(target));
return keys.reduce((clone, key) => {
if (typeof(target[key]) === "object" && !Array.isArray(target[key]) && target[key] !== null && !(target[key] instanceof NodeEvents)) clone[key] = cloneObject(target[key], {});
else clone[key] = target[key];
return clone;
}, newObject);
};
/* global window:false */
// const context = electron.webFrame.top.context;
Object.defineProperty(window, "webpackJsonp", {
get: () => electron.webFrame.top.context.webpackJsonp
let hasInitialized = false;
contextBridge.exposeInMainWorld("BetterDiscord", BdApi);
contextBridge.exposeInMainWorld("process", newProcess);
contextBridge.exposeInMainWorld("BetterDiscordPreload", () => {
if (hasInitialized) return null;
hasInitialized = true;
return BdApi;
});
electron.webFrame.top.context.global = electron.webFrame.top.context;
electron.webFrame.top.context.require = require;
electron.webFrame.top.context.Buffer = Buffer;
electron.webFrame.top.context.process = new class PatchedProcess extends NodeEvents {
get __ORIGINAL_PROCESS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED__() {return process;}
constructor() {
super();
Object.assign(this,
cloneObject(process, {}, Object.keys(NodeEvents.prototype)),
cloneObject(process, {})
);
}
};
// Load Discord's original preload
const preload = process.env.DISCORD_PRELOAD;
if (preload) {
// Restore original preload for future windows
electron.ipcRenderer.send("bd-register-preload", preload);
// Run original preload
try {
const originalKill = process.kill;
process.kill = function() {};
require(preload);
process.kill = originalKill;
}
catch (e) {
// TODO bail out
}
}
Module.globalPaths.push(path.resolve(process.env.DISCORD_APP_PATH, "..", "app.asar", "node_modules"));
init();
+22
View File
@@ -0,0 +1,22 @@
import {ipcRenderer as IPC} from "electron";
import * as IPCEvents from "common/constants/ipcevents";
export default function() {
// Load Discord's original preload
const preload = process.env.DISCORD_PRELOAD;
if (preload) {
// Restore original preload for future windows
IPC.send(IPCEvents.REGISTER_PRELOAD, preload);
// Run original preload
try {
const originalKill = process.kill;
process.kill = function() {};
__non_webpack_require__(preload);
process.kill = originalKill;
}
catch (e) {
// TODO bail out
}
}
}
+3
View File
@@ -0,0 +1,3 @@
import cloneObject from "common/clone";
export default cloneObject(process, {});
+3 -1
View File
@@ -19,7 +19,9 @@ module.exports = (env, argv) => ({
rimraf: `require("rimraf")`,
yauzl: `require("yauzl")`,
mkdirp: `require("mkdirp")`,
module: `require("module")`
module: `require("module")`,
os: `require("os")`,
net: `require("net")`
},
resolve: {
extensions: [".js"],