I have code where I have a function defined in a seperate file, and I need to run it locally in another file in order for it to access local variables there and set their value. My only solution I have found was to import it and use an eval() to execute it locally. I am using typescript and have the code being bundled via rollup.
#Locally execute function.
16 messages · Page 1 of 1 (latest)
The function is held in a global array such as ```js
// These 2 arrays are set to the contents of arrays imported from another file
const functions = [
fixThing() {/stuff/},
fixThing2() {/stuff/}
]
const ids = ["Thing","Thing2"]
// Id0.lengths will always equal functions.length
let localVar = 0;
for (let i = 0; i < ids.length; i++) {
// Execute all functions in array
eval(functions[i] + fix${ids[i]}());
}```
The functions in the functions array need to be able to access "localVar" and "localVar" cannot be exporte
Using functions[i].call() is unable to access localVar and throws undefined error.
Can you show an example of the file with functions and what the array actually looks like
Why can't they be called directly?
I receive an error of that functions[i] is not a function
I did not want to share because I am self conscious about my shitty but functional code
./cct.ts
// entity is a local variable in the location
import { Mod } from "mods/mod";
import { registerModFix } from "./handler";
export function fixCCT() {
//@ts-expect-error // here since entity is not defined
if (entity.components.CommandController && !entity.components.CommandController.command.startsWith("return;"))
//@ts-expect-error // here since entity is not defined
entity.components.CommandController.command = `return;\n${entity.components.CommandController.command}`;
}
./handler.ts
const functions = {};
export function registerModFix(id, func, when) {
functions[id] = { func, when };
}
export function runPossibleFixed(now): [{}, string[]] {
let returnFuncs = {};
let returnIds = [];
for (const id in functions) {
const { func, when } = functions[id];
if (now == when) {
returnFuncs[id] = func;
returnIds.push(id);
}
}
return [returnFuncs, returnIds];
}
// Other file
registerModFix("CCT", fixCCT, "preEntityPlaceDeserialize");```
snippet of ./fileNameUnimportant.ts
//...
// entity is typeof Entity
const entity = metaBuilding.createEntity({
root,
origin: Vector.fromSerializedObject(staticData.origin),
rotation: staticData.rotation,
originalRotation: staticData.originalRotation,
rotationVariant: data.rotationVariant,
variant: data.variant,
});
entity.uid = payload.uid;
this.deserializeComponents(root, entity, payload.components);
if (WhoCares.prototype.forceLoad) {
const fixes = runPossibleFixed("preEntityPlaceDeserialize");
const preEntityPlaceDeserialize = fixes[0],
ids = fixes[1];
for (let i = 0; i < ids.length; i++) {
eval(preEntityPlaceDeserialize[i] + `fix${ids[i]}()`); // Works perfect. There arent any security issues with this method. Eval is Evil.
preEntityPlaceDeserialize[i]() // entity is not defined
preEntityPlaceDeserialize[i].call() // entity is not defined
new Function(preEntityPlaceDeserialize[i])(); // doesnt execute
}
}
//...
I am definitely doing this wrong but it worked and i liked it until i realized i was using an eval
I want the functions that are registered via registerModFix(...) to be able to access all local varibles in the location they are ran, without passing them to the function explicitly
preEntityPlaceDeserializei // entity is not defined
preEntityPlaceDeserialize[i].call() // entity is not defined
it uses the scope where the function was declared at (another file)
new Function(preEntityPlaceDeserialize[i])(); // doesnt execute
it executesfunction fixCCT() { ... }which does nothing on its own (also have to call it)
but another issue is thatFunctionby design doesnt allow accessing variables declared outside
so sadly the only way to let it access local variables directly is eval, but passing arguments would be the proper way
the project looks like monkey-patching existing functions? if the function already accepts other arguments you could also wrap it or do it like this: https://guide.replugged.dev/docs/plugins/injecting#injecting-into-a-module
Learn how to inject into webpack modules and change their behavior
it is a funky system, but it is meant to run additional code depending on certain mods installed to the entity before registering and placing it
I built it with the hopes of only having to add the following code with a unique LOCATIONID and have everything else modified outside of the code there. js if (WhoCares.prototype.forceLoad) { const fixes = runPossibleFixed("LOCATIONID"); const preEntityPlaceDeserialize = fixes[0], ids = fixes[1]; for (let i = 0; i < ids.length; i++) { eval(preEntityPlaceDeserialize[i] + `fix${ids[i]}()`); } }