modify kiri ui to use updated dependency management

This commit is contained in:
Stewart Allen 2022-02-22 00:05:29 -05:00
commit d7be37478d
38 changed files with 300 additions and 230 deletions

283
app.js
View file

@ -39,6 +39,12 @@ const EventEmitter = require('events');
class AppEmitter extends EventEmitter {}
const events = new AppEmitter();
function addonce(array, v) {
if (array.indexOf(v) < 0) {
array.push(v);
}
};
function init(mod) {
startTime = time();
lastmod = mod.util.lastmod;
@ -52,54 +58,120 @@ function init(mod) {
dversion = debug ? `_${version}` : version;
cacheDir = mod.util.datadir("cache");
let depcache = {};
const approot = "main/gapp";
const refcache = {};
const callstack = [];
let xxxx = false;
function find_deps(path, seen = [], uses = []) {
let cached = depcache[path];
if (cached) {
return cached;
}
if (seen.indexOf(path) >= 0) {
if (debug > 1) {
console.log(`circular dependency at ${path}`, seen);
function find_refs(cache, path) {
let rec = refcache[path];
if (rec) {
let crec = cache[path];
if (!crec) {
cache[path] = rec;
for (let d of rec.deps) find_refs(cache, d);
for (let u of rec.deps) find_refs(cache, u);
}
return [];
return;
}
seen.push(path);
let deps = [ "main/gapp" ];
let lines = fs.readFileSync(`${dir}/src/${path}.js`)
callstack.push(path);
rec = cache[path] = refcache[path] = {
uses: [],
deps: [ approot ]
};
let full = `${dir}/src/${path}.js`;
try {
fs.lstatSync(full);
} catch (e) {
console.log({missing: full, callstack});
throw e;
}
let lines = fs.readFileSync(full)
.toString()
.split('\n');
for (let line of lines) {
let arr, pos;
let upos = line.indexOf('// use:');
if (upos >= 0) {
let use = line.substring(upos + 7).trim().replace('.','/');
if (uses.indexOf(use) < 0) {
uses.push(use);
}
continue;
arr = rec.uses;
pos = upos + 7;
}
let dpos = line.indexOf('// dep:');
if (dpos >= 0) {
let dep = line.substring(dpos + 7).trim().replace('.','/');
if (deps.indexOf(dep) < 0) {
deps.push(dep);
}
let deep = find_deps(dep, seen, uses);
deps = deps.filter(p => deep.indexOf(p) < 0);
// deeper dependencies go first
deps = [...deep, ...deps];
arr = rec.deps;
pos = dpos + 7;
}
if (upos >= 0 && dpos >= 0) {
console.log(`invalid line: ${line}`);
process.exit();
}
if (arr && pos >= 0) {
let path = line.substring(pos).trim().replace(/\./g,'/').trim();
addonce(arr, path);
find_refs(cache, path);
}
}
depcache[path] = deps;
return deps;
// if (xxxx) console.log({path, ...rec});
callstack.pop();
}
// return record position indicated by path
function pos(path, list) {
for (let i=0; i<list.length; i++) {
if (list[i].path === path) {
return i;
}
}
console.log(`not found: ${path}`);
process.exit();
}
function order_refs(cache) {
const recs = Object.entries(cache).map(entry => {
return { path: entry[0], deps: entry[1].deps }
}).sort((a,b) => {
return a.path === b.path ? 0 : a.path < b.path ? -1 : 1;
});
if (xxxx) console.log({ordering: recs});
// for each rec, ensure that dependencies are inserted before it
let lrec = recs.slice();
for (let rec of lrec) {
let { path, deps } = rec;
for (let dep of deps) {
let rpos = pos(path, recs);
let dpos = pos(dep, recs);
if (dpos > rpos) {
let drec = recs[dpos];
// remove old dep record
recs.splice(dpos, 1);
// insert dep before
recs.splice(rpos, 0, drec);
let nrpos = pos(path, recs);
let ndpos = pos(dep, recs);
let fail = nrpos != ndpos + 1;
// if (xxxx) { console.log({move: dep, dpos, before: path, rpos}); }
if (fail) {
console.log({move: dep, dpos, before: path, rpos, ndpos, nrpos, recs: recs.slice(0,10)});
process.exit();
}
}
}
}
if (xxxx) console.log({recs});
return recs.map(rec => rec.path);
}
// process script dependencies, expand paths
for (let [key,val] of Object.entries(script)) {
let nval = val.map(p => p.charAt(0) === '&' ? p.substring(1) : p);
let modd = false;
let uses = [];
for (let [ key, val ] of Object.entries(script)) {
if (val.indexOf(approot) < 0) {
val = [ approot, ...val ];
}
const list = val.map(p => p.charAt(0) === '&' ? p.substring(1) : p);
const cache = {};
const roots = [];
// xxxx = key === "kiri_work";
// for each path in the list, find deps and add to list
for (let path of val) {
let fc = path.charAt(0);
if (fc === '@') {
@ -107,38 +179,25 @@ function init(mod) {
}
if (fc === '&') {
path = path.substring(1);
} else {
continue;
}
let uses = [];
let deps = find_deps(path, [], uses);
if (uses.length) {
let miss = uses.filter(u => deps.indexOf(u) < 0);
if (miss.length) {
val.appendAll(miss);
}
// console.log({key, uses, miss, deps});
deps.appendAll(miss);
}
if (deps) {
// remove deps already in list
deps = deps.filter(p => nval.indexOf(p) < 0);
let ppos = nval.indexOf(path);
if (ppos < 0) {
throw `missing ${path} in nval`;
}
// inject deps
nval.splice(ppos, 0, ...deps);
modd = true;
}
// if list is modified, substitute
if (modd) {
if (debug > 1) {
console.log({path, val, nval});
}
val = nval;
addonce(roots, path);
}
find_refs(cache, path);
}
if (xxxx) console.log({processing: key, val});
let refs = order_refs(cache).filter(p => roots.indexOf(p) < 0);
// remove paths that are in refs
let paths = list.filter(p => {
if (p.charAt(0) === '&') {
p = p.substring(1);
}
return refs.indexOf(p) < 0 && roots.indexOf(p) < 0;
});
// when dependency roots exist, re-write val array
if (roots.length) {
val = [...refs, ...paths, ...roots];
}
// val.splice(1, 0, ...roots);
if (xxxx) console.log({key, cache, refs, paths, roots, val});
script[key] = val.map(p => p.charAt(0) !== '@' ? `src/${p}.js` : p);
}
@ -270,8 +329,9 @@ function initModule(mod, file, dir) {
if (opt.end) {
codelist.push(path);
} else {
let io = Math.max(0, codelist.indexOf('@inject'));
codelist.splice(io, 0, path);
codelist.push(path);
// let io = Math.max(0, codelist.indexOf('@inject'));
// codelist.splice(io, 0, path);
}
if (opt.cachever) {
cachever[path] = opt.cachever;
@ -322,89 +382,15 @@ function initModule(mod, file, dir) {
const script = {
kiri : [
"main/gapp",
"moto/license",
"main/kiri",
"@inject",
"ext/three",
"ext/three-bgu",
"ext/three-svg",
"ext/jszip",
"ext/clip2",
"ext/tween",
"ext/fsave",
// "ext/earcut",
"ext/base64",
"add/array",
"add/three",
"geo/base",
"geo/point",
"geo/points",
"geo/slope",
"geo/line",
"geo/bounds",
"geo/polygons",
"geo/polygon",
"geo/mesh",
"data/local",
"data/index",
"moto/ajax",
"moto/orbit",
"moto/space",
"load/3mf",
"load/obj",
"load/stl",
"load/svg",
"load/url",
"load/file",
"moto/broker",
"moto/webui",
"kiri/conf",
"kiri/consts",
"kiri/utils",
"kiri/stats",
"kiri/api",
"kiri/ui",
"kiri/pack",
"kiri/lang",
"kiri/lang-en",
"kiri/files",
"kiri/slice",
"kiri/layers",
"kiri/client",
"kiri-mode/fdm/fill",
"kiri-mode/fdm/driver",
"kiri-mode/fdm/client",
"kiri-mode/sla/driver",
"kiri-mode/sla/client",
"kiri-mode/cam/driver",
"kiri-mode/cam/client",
"kiri-mode/cam/tool",
"kiri-mode/cam/animate",
"kiri-mode/laser/driver",
"kiri/alerts",
"kiri/stack",
"kiri/stacks",
"kiri/widget",
"kiri/widgets",
"kiri/function",
"kiri/platform",
"kiri/selection",
"kiri/settings",
"kiri/codec",
"kiri/main",
"kiri/init",
"kiri/do",
"kiri/export",
"kiri/tools",
"kiri/frame",
"@devices",
"@icons",
"&main/kiri",
"&kiri/lang-en"
],
kiri_work : [
"main/gapp",
// "main/gapp",
"moto/license",
"main/kiri",
"@inject",
"ext/three",
"ext/pngjs",
@ -456,12 +442,12 @@ const script = {
"kiri-mode/laser/driver",
"kiri/widget",
"kiri/codec",
"kiri/worker"
"kiri/worker",
"main/kiri",
],
kiri_pool : [
"main/gapp",
// "main/gapp",
"moto/license",
"main/kiri",
"@inject",
"ext/clip2",
"ext/earcut",
@ -486,10 +472,11 @@ const script = {
"kiri/layers",
"kiri/widget",
"kiri/codec",
"kiri/minion"
"kiri/minion",
"main/kiri",
],
engine : [
"main/gapp",
// "main/gapp",
"moto/license",
"main/kiri",
"@inject",
@ -520,11 +507,11 @@ const script = {
"kiri-run/engine"
],
frame : [
"main/gapp",
// "main/gapp",
"kiri-run/frame"
],
meta : [
"main/gapp",
// "main/gapp",
"moto/license",
"main/meta",
],