Add timed GIF load, stitch, and save nodes; modular Krea 2 editors and prompt encoders; a downscale node; and compatible Set/Get frontend nodes. Also improve video-save progress and chooser positioning, update schema and release checks, and bump the package version to 3.3.1.
88 lines
4.0 KiB
JavaScript
88 lines
4.0 KiB
JavaScript
// Run with node scripts/check_set_get.mjs. No server or personal files needed.
|
|
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs';
|
|
import vm from 'node:vm';
|
|
|
|
const source = fs.readFileSync(new URL('../web/nodes/mxd_set_get.js', import.meta.url), 'utf8')
|
|
.replace(/^import .*;\r?\n/gm, '');
|
|
const run = context => vm.runInContext(`(async () => {${source}\n})()`, context);
|
|
|
|
function environment(extensions = [], existing = {}) {
|
|
const registered = [];
|
|
class Node {
|
|
constructor() { this.properties = {}; this.inputs = []; this.outputs = []; this.widgets = []; }
|
|
addInput(name, type) { this.inputs.push({ name, type, link: null }); }
|
|
addOutput(name, type) { this.outputs.push({ name, type, links: [] }); }
|
|
addWidget(type, name, value, callback, options) {
|
|
const widget = { type, name, value, callback, options };
|
|
this.widgets.push(widget); return widget;
|
|
}
|
|
serialize() { return { type: this.type, widgets_values: this.widgets.map(w => w.value) }; }
|
|
}
|
|
const LiteGraph = {
|
|
LGraphNode: Node, registered_node_types: { ...existing },
|
|
registerNodeType(key, cls) {
|
|
assert.ok(!this.registered_node_types[key], `Duplicate ${key}`);
|
|
cls.prototype.type = key; this.registered_node_types[key] = cls;
|
|
}
|
|
};
|
|
const context = vm.createContext({
|
|
LiteGraph, window: {}, console, setTimeout, clearTimeout,
|
|
api: { getExtensions: async () => extensions },
|
|
app: {
|
|
registerExtension: ext => registered.push(ext),
|
|
canvas: { setDirty() {} },
|
|
ui: { settings: { getSettingValue() { return false; } } }
|
|
}
|
|
});
|
|
return { context, registered, LiteGraph };
|
|
}
|
|
|
|
// Detection is based on the served file list, even before KJ runs its code.
|
|
for (const url of [
|
|
'/extensions/comfyui-kjnodes/js/setgetnodes.js',
|
|
'/extensions/renamed%20KJ%20pack/js/setgetnodes.js?version=2'
|
|
]) {
|
|
const env = environment([url]);
|
|
await run(env.context);
|
|
assert.equal(env.registered.length, 0);
|
|
assert.equal(env.context.window.kjNodes, undefined);
|
|
}
|
|
const existing = environment([], { SetNode: class {}, GetNode: class {} });
|
|
await run(existing.context);
|
|
assert.equal(existing.registered.length, 0);
|
|
const failed = environment();
|
|
failed.context.api.getExtensions = async () => { throw new Error('simulated offline'); };
|
|
failed.context.console = { warn() {} };
|
|
await run(failed.context);
|
|
assert.equal(failed.registered.length, 0);
|
|
|
|
// Two MXD installations racing must install only one provider.
|
|
const env = environment(['/extensions/ComfyUI-MaxedOut/nodes/mxd_set_get.js']);
|
|
await Promise.all([run(env.context), run(env.context)]);
|
|
assert.equal(new Set(env.registered.map(e => e.name)).size, env.registered.length);
|
|
assert.equal(env.registered.filter(e => e.name === 'KJNodes.SetNode').length, 1);
|
|
for (const ext of env.registered) ext.registerCustomNodes?.();
|
|
assert.deepEqual(Object.keys(env.LiteGraph.registered_node_types).sort(), ['GetNode', 'SetNode']);
|
|
const { SetNode, GetNode } = env.LiteGraph.registered_node_types;
|
|
const setter = new SetNode();
|
|
const getter = new GetNode();
|
|
setter.widgets[0].value = getter.widgets[0].value = 'VAE';
|
|
setter.inputs[0] = { name: 'VAE', type: 'VAE', link: 7 };
|
|
const upstream = { id: 1, type: 'VAELoader' };
|
|
const link = { id: 7, origin_id: 1, origin_slot: 0, target_id: 2, target_slot: 0, type: 'VAE' };
|
|
const graph = { _nodes: [upstream, setter, getter], _links: { 7: link }, getNodeById: id => id === 1 ? upstream : undefined };
|
|
setter.graph = getter.graph = graph;
|
|
getter.onRename();
|
|
assert.equal(getter.findSetter(graph), setter);
|
|
assert.equal(getter.outputs[0].type, 'VAE');
|
|
assert.equal(getter.getInputLink(0), link);
|
|
assert.equal(getter.serialize().widgets_values[0], 'VAE');
|
|
// Renaming a setter must update the paired getter's saved name.
|
|
setter.properties.previousName = 'VAE';
|
|
setter.widgets[0].value = 'Shared VAE';
|
|
setter.update();
|
|
assert.equal(getter.widgets[0].value, 'Shared VAE');
|
|
assert.equal(getter.getInputLink(0), link);
|
|
console.log('OK: Set/Get provider coexistence, singleton, routing, serialization and rename checks');
|