pref: on error.

This commit is contained in:
Rintim 2024-01-12 20:51:19 +08:00
parent b11c1972d8
commit b552dbfd01
No known key found for this signature in database
GPG Key ID: BE9E1EA615BACFCF
1 changed files with 117 additions and 128 deletions

View File

@ -8,6 +8,7 @@ import { UI as ui } from '../ui/index.js';
import { userAgent } from '../util/index.js';
import * as config from '../util/config.js';
import { promiseErrorHandlerMap } from '../util/browser.js';
import { gnc } from '../gnc/index.js';
import { importCardPack, importCharacterPack, importExtension, importMode } from './import.js';
@ -57,6 +58,7 @@ export async function boot() {
_status.event = lib.element.GameEvent.initialGameEvent();
setWindowListener();
await setOnError();
// 无名杀更新日志
if (window.noname_update) {
@ -751,33 +753,123 @@ function setServerIndex() {
}
}
function setWindowListener() {
/**
* @type { [Error, NodeJS.CallSite[]][] }
*/
const errorList = [];
// 这他娘的能捕获浏览器控制台里的输入值,尽量别用
// 在火狐里无效
Error.prepareStackTrace = function (e, stackTraces) {
errorList.push([e, stackTraces]);
};
// 已经有用了
window.addEventListener("unhandledrejection", promiseRejectionEvent => {
promiseRejectionEvent.promise.catch(e => {
const result = errorList.find(v => v[0] === e);
if (result) {
// @ts-ignore
window.onerror(
result[0].message,
result[1][0].getScriptNameOrSourceURL() || void 0,
result[1][0].getLineNumber() || void 0,
result[1][0].getColumnNumber() || void 0,
result[0]
);
}
});
async function setOnError() {
const [core] = get.coreInfo();
const promiseErrorHandler = new ((core in promiseErrorHandlerMap) ? promiseErrorHandlerMap[core] : promiseErrorHandlerMap.other);
if (promiseErrorHandler.onLoad) await promiseErrorHandler.onLoad();
window.addEventListener("unhandledrejection", async (event) => {
if (promiseErrorHandler.onHandle) await promiseErrorHandler.onHandle(event);
});
window.onerror = function (msg, src, line, column, err) {
if (promiseErrorHandler.onErrorPrepare) promiseErrorHandler.onErrorPrepare();
const winPath = window.__dirname ? ('file:///' + (__dirname.replace(new RegExp('\\\\', 'g'), '/') + '/')) : '';
let str = `错误文件: ${typeof src == 'string' ? decodeURI(src).replace(lib.assetURL, '').replace(winPath, '') : '未知文件'}`;
str += `\n错误信息: ${msg}`;
const tip = lib.getErrorTip(msg);
if (tip) str += `\n错误提示: ${tip}`;
str += `\n行号: ${line}`;
str += `\n列号: ${column}`;
const version = Reflect.has(lib, 'version') ? Reflect.get(lib, 'version') : '';
const reg = /[^\d.]/;
const match = version.match(reg) != null;
str += '\n' + `${match ? '游戏' : '无名杀'}版本: ${version || '未知版本'}`;
if (match) str += '\n⚠您使用的游戏代码不是源于libccy/noname无名杀官方仓库请自行寻找您所使用的游戏版本开发者反馈';
if (_status && _status.event) {
let evt = _status.event;
str += `\nevent.name: ${evt.name}\nevent.step: ${evt.step}`;
// @ts-ignore
if (evt.parent) str += `\nevent.parent.name: ${evt.parent.name}\nevent.parent.step: ${evt.parent.step}`;
// @ts-ignore
if (evt.parent && evt.parent.parent) str += `\nevent.parent.parent.name: ${evt.parent.parent.name}\nevent.parent.parent.step: ${evt.parent.parent.step}`;
if (evt.player || evt.target || evt.source || evt.skill || evt.card) {
str += '\n-------------';
}
if (evt.player) {
if (lib.translate[evt.player.name]) str += `\nplayer: ${lib.translate[evt.player.name]}[${evt.player.name}]`;
else str += '\nplayer: ' + evt.player.name;
let distance = get.distance(_status.roundStart, evt.player, 'absolute');
if (distance != Infinity) {
str += `\n座位号: ${distance + 1}`;
}
}
if (evt.target) {
if (lib.translate[evt.target.name]) str += `\ntarget: ${lib.translate[evt.target.name]}[${evt.target.name}]`;
else str += '\ntarget: ' + evt.target.name;
}
if (evt.source) {
if (lib.translate[evt.source.name]) str += `\nsource: ${lib.translate[evt.source.name]}[${evt.source.name}]`;
else str += '\nsource: ' + evt.source.name;
}
if (evt.skill) {
if (lib.translate[evt.skill]) str += `\nskill: ${lib.translate[evt.skill]}[${evt.skill}]`;
else str += '\nskill: ' + evt.skill;
}
if (evt.card) {
if (lib.translate[evt.card.name]) str += `\ncard: ${lib.translate[evt.card.name]}[${evt.card.name}]`;
else str += '\ncard: ' + evt.card.name;
}
}
str += '\n-------------';
if (typeof line == 'number' && (typeof Reflect.get(game, 'readFile') == 'function' || location.origin != 'file://')) {
const createShowCode = function (lines) {
let showCode = '';
if (lines.length >= 10) {
if (line > 4) {
for (let i = line - 5; i < line + 6 && i < lines.length; i++) {
showCode += `${i + 1}| ${line == i + 1 ? '⚠️' : ''}${lines[i]}\n`;
}
} else {
for (let i = 0; i < line + 6 && i < lines.length; i++) {
showCode += `${i + 1}| ${line == i + 1 ? '⚠️' : ''}${lines[i]}\n`;
}
}
} else {
showCode = lines.map((_line, i) => `${i + 1}| ${line == i + 1 ? '⚠️' : ''}${_line}\n`).toString();
}
return showCode;
};
//协议名须和html一致(网页端防跨域)且文件是js
if (typeof src == 'string' && src.startsWith(location.protocol) && src.endsWith('.js')) {
//获取代码
const codes = lib.init.reqSync('local:' + decodeURI(src).replace(lib.assetURL, '').replace(winPath, ''));
if (codes) {
const lines = codes.split("\n");
str += '\n' + createShowCode(lines);
str += '\n-------------';
}
}
//解析parsex里的content fun内容(通常是技能content)
else if (err && err.stack && err.stack.split('\n')[1].trim().startsWith('at Object.eval [as content]')) {
const codes = _status.event.content;
if (typeof codes == 'function') {
const lines = codes.toString().split("\n");
str += '\n' + createShowCode(lines);
str += '\n-------------';
}
}
}
if (err && err.stack) str += '\n' + decodeURI(err.stack).replace(new RegExp(lib.assetURL, 'g'), '').replace(new RegExp(winPath, 'g'), '');
alert(str);
Reflect.set(window, 'ea', Array.from(arguments));
Reflect.set(window, 'em', msg);
Reflect.set(window, 'el', line);
Reflect.set(window, 'ec', column);
Reflect.set(window, 'eo', err);
game.print(str);
if (promiseErrorHandler.onErrorFinish) promiseErrorHandler.onErrorFinish();
// @ts-ignore
if (!lib.config.errstop) {
_status.withError = true;
game.loop();
}
};
}
function setWindowListener() {
window.onkeydown = function (e) {
if (!Reflect.has(ui, 'menuContainer') || !Reflect.get(ui, 'menuContainer').classList.contains('hidden')) {
if (e.keyCode == 116 || ((e.ctrlKey || e.metaKey) && e.keyCode == 82)) {
@ -875,107 +967,4 @@ function setWindowListener() {
// }
}
};
window.onerror = function (msg, src, line, column, err) {
errorList.length = 0;
const winPath = window.__dirname ? ('file:///' + (__dirname.replace(new RegExp('\\\\', 'g'), '/') + '/')) : '';
let str = `错误文件: ${typeof src == 'string' ? decodeURI(src).replace(lib.assetURL, '').replace(winPath, '') : '未知文件'}`;
str += `\n错误信息: ${msg}`;
const tip = lib.getErrorTip(msg);
if (tip) str += `\n错误提示: ${tip}`;
str += `\n行号: ${line}`;
str += `\n列号: ${column}`;
const version = Reflect.has(lib, 'version') ? Reflect.get(lib, 'version') : '';
const reg = /[^\d.]/;
const match = version.match(reg) != null;
str += '\n' + `${match ? '游戏' : '无名杀'}版本: ${version || '未知版本'}`;
if (match) str += '\n⚠您使用的游戏代码不是源于libccy/noname无名杀官方仓库请自行寻找您所使用的游戏版本开发者反馈';
if (_status && _status.event) {
let evt = _status.event;
str += `\nevent.name: ${evt.name}\nevent.step: ${evt.step}`;
// @ts-ignore
if (evt.parent) str += `\nevent.parent.name: ${evt.parent.name}\nevent.parent.step: ${evt.parent.step}`;
// @ts-ignore
if (evt.parent && evt.parent.parent) str += `\nevent.parent.parent.name: ${evt.parent.parent.name}\nevent.parent.parent.step: ${evt.parent.parent.step}`;
if (evt.player || evt.target || evt.source || evt.skill || evt.card) {
str += '\n-------------';
}
if (evt.player) {
if (lib.translate[evt.player.name]) str += `\nplayer: ${lib.translate[evt.player.name]}[${evt.player.name}]`;
else str += '\nplayer: ' + evt.player.name;
let distance = get.distance(_status.roundStart, evt.player, 'absolute');
if (distance != Infinity) {
str += `\n座位号: ${distance + 1}`;
}
}
if (evt.target) {
if (lib.translate[evt.target.name]) str += `\ntarget: ${lib.translate[evt.target.name]}[${evt.target.name}]`;
else str += '\ntarget: ' + evt.target.name;
}
if (evt.source) {
if (lib.translate[evt.source.name]) str += `\nsource: ${lib.translate[evt.source.name]}[${evt.source.name}]`;
else str += '\nsource: ' + evt.source.name;
}
if (evt.skill) {
if (lib.translate[evt.skill]) str += `\nskill: ${lib.translate[evt.skill]}[${evt.skill}]`;
else str += '\nskill: ' + evt.skill;
}
if (evt.card) {
if (lib.translate[evt.card.name]) str += `\ncard: ${lib.translate[evt.card.name]}[${evt.card.name}]`;
else str += '\ncard: ' + evt.card.name;
}
}
str += '\n-------------';
if (typeof line == 'number' && (typeof Reflect.get(game, 'readFile') == 'function' || location.origin != 'file://')) {
const createShowCode = function (lines) {
let showCode = '';
if (lines.length >= 10) {
if (line > 4) {
for (let i = line - 5; i < line + 6 && i < lines.length; i++) {
showCode += `${i + 1}| ${line == i + 1 ? '⚠️' : ''}${lines[i]}\n`;
}
} else {
for (let i = 0; i < line + 6 && i < lines.length; i++) {
showCode += `${i + 1}| ${line == i + 1 ? '⚠️' : ''}${lines[i]}\n`;
}
}
} else {
showCode = lines.map((_line, i) => `${i + 1}| ${line == i + 1 ? '⚠️' : ''}${_line}\n`).toString();
}
return showCode;
};
//协议名须和html一致(网页端防跨域)且文件是js
if (typeof src == 'string' && src.startsWith(location.protocol) && src.endsWith('.js')) {
//获取代码
const codes = lib.init.reqSync('local:' + decodeURI(src).replace(lib.assetURL, '').replace(winPath, ''));
if (codes) {
const lines = codes.split("\n");
str += '\n' + createShowCode(lines);
str += '\n-------------';
}
}
//解析parsex里的content fun内容(通常是技能content)
else if (err && err.stack && err.stack.split('\n')[1].trim().startsWith('at Object.eval [as content]')) {
const codes = _status.event.content;
if (typeof codes == 'function') {
const lines = codes.toString().split("\n");
str += '\n' + createShowCode(lines);
str += '\n-------------';
}
}
}
if (err && err.stack) str += '\n' + decodeURI(err.stack).replace(new RegExp(lib.assetURL, 'g'), '').replace(new RegExp(winPath, 'g'), '');
alert(str);
Reflect.set(window, 'ea', Array.from(arguments));
Reflect.set(window, 'em', msg);
Reflect.set(window, 'el', line);
Reflect.set(window, 'ec', column);
Reflect.set(window, 'eo', err);
game.print(str);
// @ts-ignore
if (!lib.config.errstop) {
_status.withError = true;
game.loop();
}
};
}