Random silliness: Quest's "invoke" in JS
mrangel
11 Dec 2020, 17:40Random I know.
This was an issue back with QuestJS, the one that tried to convert Quest 5.x games to javascript code. They had a problem that a function's parameters weren't known when it was created. Because Quest's invoke
takes a script parameter, and a dictionary of parameters, and the parameter names come from the dictionary.
It randomly popped into my head how you could do this lately. So I present: a javascript function that messes with another javascript function.
function Quest_invoke (script, params) {
eval("(" + script.toString().replace(/^\s*(function\s*.*?\()/, "$1"+Object.keys(params).join(",")) + ")").apply(null, Object.values(params));
}
function Quest_do (object, scriptname, params) {
eval("(" + object[scriptname].toString().replace(/^\s*(function\s*.*?\()/, "$1"+Object.keys(params).join(",")) + ")").apply(object, Object.values(params));
}
This is probably useless now; but if someone wants to revive the idea of making a new engine to work with the old files it could be useful.
Richard Headkid
11 Dec 2020, 17:47By default, you can't do eval
due to the security settings in Quest 6.
https://github.com/ThePix/QuestJS/wiki/Code-guidelines#content-security-policy
mrangel
11 Dec 2020, 19:09Sorry. You can delete this post if you want to keep irrelevant stuff off the forum.
But if you want to do this without eval, you should be able to use some terrible voodoo code like:
function Quest_invoke (script, params) {
var stash = Object.keys(params);
stash.push(script.toString().replace(/^.*?\{(.*)\}.*?$/s, "$1"));
stash.unshift(undefined);
var modified_script = new (Function.prototype.bind.apply(Function, stash));
modified_script.apply(null, Object.values(params));
}
(more proof that I can't let go of an unsolved problem even when it's years past being relevant)
For reference:
new (Function.prototype.bind.apply(SomeClassName, some_array));
is equivalent to:
new SomeClassName(some_array[1], some_array[2], some_array[3] …)
I'm using that with the Function
constructor, because I have an array of parameter names (from Object.keys(params)
). So I can then call the newly created function by using its apply
method to supply an array of parameter values rather than the parameters individually.
Richard Headkid
11 Dec 2020, 19:55Curses!
Uncaught EvalError: call to Function() blocked by CSP
Quest_invoke debugger eval code:4
<anonymous> debugger eval code:12
debugger eval code:4:25
Richard Headkid
11 Dec 2020, 19:56I can't let go of an unsolved problem even when it's years past being relevant
Neither can I, good sir. Neither can I.
Unsolved problems haunt me.
mrangel
11 Dec 2020, 20:23I wasn't sure if the Function constructor would count as an eval or not; guess I'm out of luck there.
Richard Headkid
11 Dec 2020, 20:55It was a valiant effort.
I would have used it, just to prove it could be done.