This repository has been archived on 2023-11-14. You can view files and clone it, but cannot push or open issues/pull-requests.
vogue/Instance.js

109 lines
2.8 KiB
JavaScript
Raw Normal View History

2021-05-02 17:42:04 -04:00
import Serializable from './Serializable.js';
import minify from './minify.js';
import debug from 'debug';
import _ from 'lodash';
const log = debug('vogue:instance');
2021-05-02 17:42:04 -04:00
export default class Instance extends Serializable {
module = null;
links = {}
system = null;
2021-05-06 23:05:36 -04:00
context = null;
locals = [];
internalFunctions = {};
2021-05-02 17:42:04 -04:00
// reconstruct context when we need it...
2021-05-06 23:05:36 -04:00
createContext() {
let ctx = {};
2021-05-02 17:42:04 -04:00
for(const name in this.links) {
ctx[name] = this.links[name];
}
2021-05-06 23:05:36 -04:00
for(const name in this.module.imports) {
ctx[name] = this.module.imports[name];
this.locals.push(name);
2021-05-06 23:05:36 -04:00
}
ctx = {
...ctx,
...this.system.staticInstances,
...this.internalFunctions
}
for(const identifier in this.system.staticInstances) {
this.locals.push(identifier);
}
2021-05-02 17:42:04 -04:00
ctx.create = this.system.newInstance.bind(this.system);
this.locals.push('create');
2021-05-06 23:05:36 -04:00
this.context = ctx;
2021-05-02 17:42:04 -04:00
};
ready = false;
2021-05-02 17:42:04 -04:00
constructor(module, location, parameters, system) {
super();
this.module = module;
this.location = location;
this.system = system;
for(const name of this.module.links.optional.arrays) this.links[name] = [];
for(const name of this.module.links.optional.single) this.links[name] = null;
for(const fnName in this.module.functions) {
this.internalFunctions[fnName] =
this.invokeInternal.bind(this, fnName);
}
2021-05-06 23:05:36 -04:00
this.createContext();
this._link = new Proxy(this, {
get(target, prop, receiver) {
if(prop === 'restore') return undefined;
if(prop in target.module.functions) {
return target.invokeInternal.bind(target, prop);
}
return undefined;
}
});
2021-05-02 17:42:04 -04:00
}
hasPublicFunction(name) {
return (name in this.module.functions);
}
2021-05-02 17:42:04 -04:00
invokeInternal(name, ...args) {
log('invoking', this.module.name.full + '.' + name, 'with args', args);
const content = this.module.functions[name].code;
const passingArguments = _.zipObject(this.module.functions[name].parameters, args);
if(!content) throw new TypeError(name + ' is not a function!');
return evalInContext(content, this.context, this.locals, passingArguments);
2021-05-02 17:42:04 -04:00
}
2021-05-06 23:05:36 -04:00
get link () {
return this._link;
}
2021-05-02 17:42:04 -04:00
}
function evalInContext(js, context, locals, passingArguments) {
2021-05-02 17:42:04 -04:00
//# Return the results of the in-line anonymous function we .call with the passed context
log('='.repeat(80) + 'OG Block');
log(js);
log('='.repeat(80) + 'Arguments');
log(passingArguments);
2021-05-02 17:42:04 -04:00
const that = this;
return function() {
const preminJs =
`'use strict';
(() => {
${locals.map((k) => `const ${k} = this.${k};`).join('\n\t')}
${Object.keys(passingArguments).map(name => `let ${name} = passingArguments.${name};`).join('\n\t')}
${js}
})();`;
log('='.repeat(80) + 'preminjs');
log(preminJs);
2021-05-02 17:42:04 -04:00
const newJs = minify(preminJs);
log('='.repeat(80) + 'minjs');
log(newJs);
// newJs should inject into result...
let result;
eval(newJs);
return result;
2021-05-02 17:42:04 -04:00
}.call(context);
}