BetterDiscordApp-rauenzi/renderer/src/polyfill/module.js

103 lines
3.6 KiB
JavaScript

import Logger from "common/logger";
import {compileFunction} from "./vm";
import Remote from "./remote";
import fs from "./fs";
const path = Remote.path;
export const RequireExtensions = {
".js": (module, filename) => {
const fileContent = Remote.filesystem.readFile(filename, "utf8");
module.fileContent = fileContent;
module._compile(fileContent);
return module.exports;
},
".json": (module, filename) => {
const fileContent = Remote.filesystem.readFile(filename, "utf8");
module.fileContent = fileContent;
module.exports = JSON.parse(fileContent);
return module.exports;
}
};
export default class Module {
static resolveMainFile(mod, basePath) {
const parent = path.extname(basePath) ? path.dirname(basePath) : basePath;
const files = Remote.filesystem.readDirectory(parent);
if (!Array.isArray(files)) return null;
for (const file of files) {
const ext = path.extname(file);
if (file === "package.json") {
const pkg = require(path.resolve(parent, file));
if (!Reflect.has(pkg, "main")) continue;
return path.resolve(parent, pkg.main);
}
if (path.slice(0, -ext.length) == "index" && RequireExtensions[ext]) return mod;
}
}
static getExtension(mod) {
return path.extname(mod) || Reflect.ownKeys(RequireExtensions).find(e => Remote.filesystem.exists(mod + e));
}
static getFilePath(basePath, mod) {
if (!path.isAbsolute(mod)) mod = path.resolve(basePath, mod);
const defaultExtension = path.extname(mod);
if (!defaultExtension) {
const ext = Reflect.ownKeys(RequireExtensions).find(e => Remote.filesystem.exists(mod + e));
if (ext) {
mod = mod + ext;
}
}
return fs.realpathSync(mod);
}
static _load(mod, basePath, createRequire) {
const originalReq = mod;
if (!path.isAbsolute(mod)) mod = path.resolve(basePath, mod);
const filePath = this.getFilePath(basePath, mod);
if (!Remote.filesystem.exists(filePath)) throw new Error(`Cannot find module ${mod}`);
if (window.require.cache[filePath]) return window.require.cache[filePath].exports;
const stats = Remote.filesystem.getStats(filePath);
if (stats.isDirectory()) mod = this.resolveMainFile(mod, basePath);
const ext = this.getExtension(filePath);
const loader = RequireExtensions[ext];
if (!loader) throw new Error(`Cannot find module ${originalReq}`);
const module = window.require.cache[mod] = new Module(filePath, internalModule, createRequire(mod));
loader(module, filePath);
return module.exports;
}
static get Module() {return Module;}
static get createRequire() {return Logger.warn("ContextModule", "Module.createRequire not implemented yet.");}
static get _extensions() {return RequireExtensions;}
constructor(id, parent, require) {
this.id = id;
this.path = Remote.path.dirname(id);
this.exports = {};
this.parent = parent;
this.filename = id;
this.loaded = false;
this.children = [];
this.require = require;
if (parent) parent.children.push(this);
}
_compile(code) {
const wrapped = compileFunction(code, ["require", "module", "exports", "__filename", "__dirname", "global"], this.filename);
wrapped(this.require, this, this.exports, this.filename, this.path, window);
}
}
const internalModule = new Module(".", null);