Easier plugin debugging

- Make debugging syntax errors in plugins easier by catching the errors and printing relevant information
- Fix default plugin rejected load promise resolving unexpectedly
- Fix default plugin id not stripping the search part of the url
This commit is contained in:
KatieFrogs 2022-03-04 01:26:17 +03:00
parent 6c54c45a23
commit 89b159e33a

View File

@ -20,6 +20,10 @@ class Plugins{
var name = options.name var name = options.name
if(!name && isUrl){ if(!name && isUrl){
name = script name = script
var index = name.lastIndexOf("?")
if(index !== -1){
name = name.slice(0, index)
}
var index = name.lastIndexOf("/") var index = name.lastIndexOf("/")
if(index !== -1){ if(index !== -1){
name = name.slice(index + 1) name = name.slice(index + 1)
@ -50,6 +54,7 @@ class Plugins{
return plugin return plugin
} }
remove(name){ remove(name){
if(name in this.pluginMap){
var hash = this.pluginMap[name].hash var hash = this.pluginMap[name].hash
if(hash){ if(hash){
var index = this.hashes.indexOf(hash) var index = this.hashes.indexOf(hash)
@ -58,6 +63,7 @@ class Plugins{
} }
} }
this.unload(name) this.unload(name)
}
var index = this.allPlugins.findIndex(obj => obj.name === name) var index = this.allPlugins.findIndex(obj => obj.name === name)
if(index !== -1){ if(index !== -1){
this.allPlugins.splice(index, 1) this.allPlugins.splice(index, 1)
@ -235,12 +241,14 @@ class Plugins{
default: true, default: true,
getItem: () => plugin.started, getItem: () => plugin.started,
setItem: value => { setItem: value => {
if(plugin.name in this.pluginMap){
if(plugin.started && !value){ if(plugin.started && !value){
this.stop(plugin.name) this.stop(plugin.name)
}else if(!plugin.started && value){ }else if(!plugin.started && value){
this.start(plugin.name) this.start(plugin.name)
} }
} }
}
}) })
} }
var settings = plugin.settings() var settings = plugin.settings()
@ -321,9 +329,15 @@ class PluginLoader{
try{ try{
this.module = new module.default() this.module = new module.default()
}catch(e){ }catch(e){
console.error(e)
this.error() this.error()
return var error = new Error()
error.stack = "Error initializing plugin: " + this.name + "\n" + e.stack
if(loadErrors){
return Promise.reject(error)
}else{
console.error(error)
return Promise.resolve()
}
} }
var output var output
try{ try{
@ -334,22 +348,41 @@ class PluginLoader{
output = this.module.load(this) output = this.module.load(this)
} }
}catch(e){ }catch(e){
console.error(e)
this.error() this.error()
var error = new Error()
error.stack = "Error in plugin load: " + this.name + "\n" + e.stack
if(loadErrors){
return Promise.reject(error)
}else{
console.error(error)
return Promise.resolve()
}
} }
if(typeof output === "object" && output.constructor === Promise){ if(typeof output === "object" && output.constructor === Promise){
return output.catch(e => { return output.catch(e => {
console.error(e)
this.error() this.error()
var error = new Error()
error.stack = "Error in plugin load promise: " + this.name + (e ? "\n" + e.stack : "")
if(loadErrors){
return Promise.reject(error)
}else{
console.error(error)
return Promise.resolve() return Promise.resolve()
}
}) })
} }
}, e => { }, e => {
console.error(e)
this.error() this.error()
if(loadErrors){ if(e.name === "SyntaxError"){
return Promise.reject(e) var error = new SyntaxError()
error.stack = "Error in plugin syntax: " + this.name + "\n" + e.stack
}else{ }else{
var error = e
}
if(loadErrors){
return Promise.reject(error)
}else{
console.error(error)
return Promise.resolve() return Promise.resolve()
} }
}) })
@ -370,13 +403,15 @@ class PluginLoader{
this.module.start() this.module.start()
} }
}catch(e){ }catch(e){
console.error(e) var error = new Error()
error.stack = "Error in plugin start: " + this.name + "\n" + e.stack
console.error(error)
this.error() this.error()
} }
} }
}) })
} }
stop(orderChange, error){ stop(orderChange, noError){
if(this.loaded && this.started){ if(this.loaded && this.started){
if(!orderChange){ if(!orderChange){
var stopIndex = plugins.startOrder.indexOf(this.name) var stopIndex = plugins.startOrder.indexOf(this.name)
@ -397,8 +432,10 @@ class PluginLoader{
this.module.stop() this.module.stop()
} }
}catch(e){ }catch(e){
console.error(e) var error = new Error()
if(!error){ error.stack = "Error in plugin stop: " + this.name + "\n" + e.stack
console.error(error)
if(!noError){
this.error() this.error()
} }
} }
@ -426,7 +463,9 @@ class PluginLoader{
this.module.unload() this.module.unload()
} }
}catch(e){ }catch(e){
console.error(e) var error = new Error()
error.stack = "Error in plugin unload: " + this.name + "\n" + e.stack
console.error(error)
} }
delete this.module delete this.module
} }
@ -437,7 +476,9 @@ class PluginLoader{
try{ try{
this.module.error() this.module.error()
}catch(e){ }catch(e){
console.error(e) var error = new Error()
error.stack = "Error in plugin error: " + this.name + "\n" + e.stack
console.error(error)
} }
} }
this.unload(true) this.unload(true)
@ -481,9 +522,17 @@ class EditValue{
if(this.name){ if(this.name){
this.original = this.name[0][this.name[1]] this.original = this.name[0][this.name[1]]
} }
try{
var output = this.loadCallback(this.original) var output = this.loadCallback(this.original)
}catch(e){
console.error(this.loadCallback)
var error = new Error()
error.stack = "Error editing the value of " + this.getName() + "\n" + e.stack
throw error
}
if(typeof output === "undefined"){ if(typeof output === "undefined"){
throw new Error("A value is expected to be returned") console.error(this.loadCallback)
throw new Error("Error editing the value of " + this.getName() + ": A value is expected to be returned")
} }
if(this.name){ if(this.name){
this.name[0][this.name[1]] = output this.name[0][this.name[1]] = output
@ -500,6 +549,27 @@ class EditValue{
} }
return this.original return this.original
} }
getName(){
var name = "unknown"
try{
if(this.name){
var name = (
typeof this.name[0] === "function" && this.name[0].name
|| (
typeof this.name[0] === "object" && typeof this.name[0].constructor === "function" && (
this.name[0] instanceof this.name[0].constructor ? (() => {
var consName = this.name[0].constructor.name || ""
return consName.slice(0, 1).toLowerCase() + consName.slice(1)
})() : this.name[0].constructor.name + ".prototype"
)
) || name
) + (this.name[1] ? "." + this.name[1] : "")
}
}catch(e){
name = "error"
}
return name
}
unload(){ unload(){
delete this.name delete this.name
delete this.original delete this.original
@ -513,11 +583,33 @@ class EditFunction extends EditValue{
this.original = this.name[0][this.name[1]] this.original = this.name[0][this.name[1]]
} }
var args = plugins.argsFromFunc(this.original) var args = plugins.argsFromFunc(this.original)
try{
var output = this.loadCallback(plugins.strFromFunc(this.original), args) var output = this.loadCallback(plugins.strFromFunc(this.original), args)
if(typeof output === "undefined"){ }catch(e){
throw new Error("A value is expected to be returned") console.error(this.loadCallback)
var error = new Error()
error.stack = "Error editing the function value of " + this.getName() + "\n" + e.stack
throw error
} }
if(typeof output === "undefined"){
console.error(this.loadCallback)
throw new Error("Error editing the function value of " + this.getName() + ": A value is expected to be returned")
}
try{
var output = Function(...args, output) var output = Function(...args, output)
}catch(e){
console.error(this.loadCallback)
var error = new SyntaxError()
var blob = new Blob([output], {
type: "application/javascript"
})
var url = URL.createObjectURL(blob)
error.stack = "Error editing the function value of " + this.getName() + ": Could not evaluate string, check the full string for errors: " + url + "\n" + e.stack
setTimeout(() => {
URL.revokeObjectURL(url)
}, 5 * 60 * 1000)
throw error
}
if(this.name){ if(this.name){
this.name[0][this.name[1]] = output this.name[0][this.name[1]] = output
} }