core: add jsc loader

This commit is contained in:
undefined committed 2022-02-28 14:21:44 +08:00
1 parent 5d27bce80e
commit 6a289f788d
5 files changed
+48 -39

No files matched your search

+32
View File
@@ -18,6 +18,7 @@ require('source-map-support').install({
});
const os = require('os');
const path = require('path');
const vm = require('vm');
const fs = require('fs-extra');
const argv = require('cac')().parse();
const child = require('child_process');
@@ -60,6 +61,10 @@ function transform(filename) {
return result.code;
}
const ESM = ['p-queue', 'p-timeout'];
const _script = new vm.Script('"Hydro"', { produceCachedData: true });
const bytecode = (_script.createCachedData && _script.createCachedData.call)
? _script.createCachedData()
: _script.cachedData;
require.extensions['.js'] = function loader(module, filename) {
if (ESM.filter((i) => filename.includes(i)).length || major < 14) {
return module._compile(transform(filename), filename);
@@ -70,6 +75,33 @@ require.extensions['.js'] = function loader(module, filename) {
require.extensions['.ts'] = require.extensions['.tsx'] = function loader(module, filename) {
return module._compile(transform(filename), filename);
};
require.extensions['.jsc'] = function loader(module, filename) {
const buf = fs.readFileSync(filename);
bytecode.slice(12, 16).copy(buf, 12);
if (![12, 13, 14, 15, 16, 17].filter((i) => process.version.startsWith(`v${i}`)).length) {
bytecode.slice(16, 20).copy(buf, 16);
}
// eslint-disable-next-line no-return-assign
const length = buf.slice(8, 12).reduce((sum, number, power) => sum += number * (256 ** power), 0);
let dummyCode = '';
if (length > 1) dummyCode = `"${'\u200b'.repeat(length - 2)}"`;
const script = new vm.Script(dummyCode, {
filename,
lineOffset: 0,
displayErrors: true,
cachedData: buf,
});
if (script.cachedDataRejected) throw new Error(`cacheDataRejected on ${filename}`);
const compiledWrapper = script.runInThisContext({
filename,
lineOffset: 0,
columnOffset: 0,
displayErrors: true,
});
const dirname = path.dirname(filename);
const args = [module.exports, require, module, filename, dirname, process, global];
return compiledWrapper.apply(module.exports, args);
};
function buildUrl(opts) {
let mongourl = `${opts.protocol || 'mongodb'}://`;
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "hydrooj",
"version": "3.5.4",
"version": "3.5.5",
"bin": "bin/hydrooj.js",
"main": "src/loader",
"module": "src/loader",
+2 -31
View File
@@ -105,40 +105,11 @@ export interface GDoc {
export type ownerInfo = { owner: number, maintainer?: number[] };
export interface User extends Record<string, any> {
_id: number;
_udoc: Udoc;
_dudoc: any;
_salt: string;
_hash: string;
_regip: string;
_loginip: string;
_tfa: string;
mail: string;
uname: string;
hashType: string;
priv: number;
regat: Date;
loginat: Date;
perm: bigint;
scope: bigint;
role: string;
group?: string[];
tfa: boolean;
own<T extends ownerInfo>(doc: T, checkPerm: bigint): boolean
own<T extends ownerInfo>(doc: T, exact: boolean): boolean
own<T extends ownerInfo>(doc: T): boolean
own<T extends { owner: number, maintainer?: number[] }>(doc: T): boolean;
hasPerm: (...perm: bigint[]) => boolean;
hasPriv: (...priv: number[]) => boolean;
checkPassword: (password: string) => void;
}
export type User = import('./model/user').User;
export type Udict = NumericDictionary<User>;
export interface FileInfo {
/** duplicate to filename */
/** storage path */
_id: string,
/** filename */
name: string,
+1
View File
@@ -146,6 +146,7 @@ Worker.addHandler('task.daily', async () => {
if (global.Hydro.model.system.get('server.checkUpdate')) {
await global.Hydro.script.checkUpdate?.run({}, new Logger('task/checkUpdate').debug);
}
await bus.serial('task/daily');
});
bus.on('domain/delete', (domainId) => coll.deleteMany({ domainId }));
bus.once('app/started', async () => {
+12 -7
View File
@@ -3,8 +3,8 @@ import LRU from 'lru-cache';
import { Collection, ObjectID } from 'mongodb';
import { LoginError, UserAlreadyExistError, UserNotFoundError } from '../error';
import {
FileInfo, GDoc, Udict,
Udoc, User as _User, VUdoc,
FileInfo, GDoc, ownerInfo,
Udict, Udoc, VUdoc,
} from '../interface';
import pwhash from '../lib/hash.hydro';
import { Logger } from '../logger';
@@ -18,10 +18,10 @@ import * as setting from './setting';
import * as system from './system';
import token from './token';
const coll: Collection<Udoc> = db.collection('user');
export const coll: Collection<Udoc> = db.collection('user');
// Virtual user, only for display in contest.
const collV: Collection<VUdoc> = db.collection('vuser');
const collGroup: Collection<GDoc> = db.collection('user.group');
export const collV: Collection<VUdoc> = db.collection('vuser');
export const collGroup: Collection<GDoc> = db.collection('user.group');
const logger = new Logger('model/user');
const cache = new LRU<string, User>({ max: 500, maxAge: 300 * 1000 });
@@ -45,7 +45,7 @@ export function deleteUserCache(udoc: User | Udoc | string | undefined | null, r
}
bus.on('user/delcache', (content) => deleteUserCache(JSON.parse(content), true));
class User implements _User {
export class User {
_id: number;
_udoc: Udoc;
@@ -108,6 +108,10 @@ class User implements _User {
return this;
}
own<T extends ownerInfo>(doc: T, checkPerm: bigint): boolean;
own<T extends ownerInfo>(doc: T, exact: boolean): boolean;
own<T extends ownerInfo>(doc: T): boolean;
own<T extends { owner: number, maintainer?: number[] }>(doc: T): boolean;
own(doc: any, arg1: any = false): boolean {
if (typeof arg1 === 'bigint' && !this.hasPerm(arg1)) return false;
return (typeof arg1 === 'boolean' && arg1)
@@ -135,7 +139,8 @@ class User implements _User {
const result = h(password, this._salt, this);
if (result !== true && result !== this._hash) {
throw new LoginError(this.uname);
} else if (this.hashType !== 'hydro') {
}
if (this.hashType !== 'hydro') {
// eslint-disable-next-line @typescript-eslint/no-use-before-define
UserModel.setPassword(this._id, password);
}