Merge pull request #367 from moritz89/fix-duplicate-slot-node-types

Fix duplicate slot node types
This commit is contained in:
Javi Agenjo
2023-04-10 19:00:16 +02:00
committed by GitHub
5 changed files with 945 additions and 743 deletions

1445
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -13,6 +13,7 @@
"build": "grunt build",
"start": "nodemon utils/server.js",
"test": "jest",
"test:allVersions": "./utils/test.sh",
"prettier": "npx prettier --write src/**/*.* css/**/*.*",
"lint": "npx eslint src",
"lint:fix": "npx eslint --fix src"
@@ -33,7 +34,7 @@
},
"homepage": "https://github.com/jagenjo/litegraph.js#readme",
"devDependencies": {
"@types/jest": "^29.5.0",
"@types/jest": "^28.1.3",
"eslint": "^8.37.0 ",
"eslint-plugin-jest": "^27.2.1",
"express": "^4.17.1",
@@ -42,7 +43,7 @@
"grunt-cli": "^1.2.0",
"grunt-closure-tools": "^1.0.0",
"grunt-contrib-concat": "^1.0.1",
"jest": "^29.5.0",
"jest": "^28.1.3",
"nodemon": "^1.19.4",
"rimraf": "^2.7.1"
}

View File

@@ -251,13 +251,18 @@
* @param {String|Object} type name of the node or the node constructor itself
*/
unregisterNodeType: function(type) {
var base_class = type.constructor === String ? this.registered_node_types[type] : type;
if(!base_class)
throw("node type not found: " + type );
delete this.registered_node_types[base_class.type];
if(base_class.constructor.name)
delete this.Nodes[base_class.constructor.name];
},
const base_class =
type.constructor === String
? this.registered_node_types[type]
: type;
if (!base_class) {
throw "node type not found: " + type;
}
delete this.registered_node_types[base_class.type];
if (base_class.constructor.name) {
delete this.Nodes[base_class.constructor.name];
}
},
/**
* Save a slot type and his node
@@ -265,38 +270,49 @@
* @param {String|Object} type name of the node or the node constructor itself
* @param {String} slot_type name of the slot type (variable type), eg. string, number, array, boolean, ..
*/
registerNodeAndSlotType: function(type,slot_type,out){
registerNodeAndSlotType: function(type, slot_type, out){
out = out || false;
var base_class = type.constructor === String && this.registered_node_types[type] !== "anonymous" ? this.registered_node_types[type] : type;
var sCN = base_class.constructor.type;
if (typeof slot_type == "string"){
var aTypes = slot_type.split(",");
}else if (slot_type == this.EVENT || slot_type == this.ACTION){
var aTypes = ["_event_"];
}else{
var aTypes = ["*"];
const base_class =
type.constructor === String &&
this.registered_node_types[type] !== "anonymous"
? this.registered_node_types[type]
: type;
const class_type = base_class.constructor.type;
let allTypes = [];
if (typeof slot_type === "string") {
allTypes = slot_type.split(",");
} else if (slot_type == this.EVENT || slot_type == this.ACTION) {
allTypes = ["_event_"];
} else {
allTypes = ["*"];
}
for (var i = 0; i < aTypes.length; ++i) {
var sT = aTypes[i]; //.toLowerCase();
if (sT === ""){
sT = "*";
for (let i = 0; i < allTypes.length; ++i) {
let slotType = allTypes[i];
if (slotType === "") {
slotType = "*";
}
var registerTo = out ? "registered_slot_out_types" : "registered_slot_in_types";
if (typeof this[registerTo][sT] == "undefined") this[registerTo][sT] = {nodes: []};
this[registerTo][sT].nodes.push(sCN);
const registerTo = out
? "registered_slot_out_types"
: "registered_slot_in_types";
if (this[registerTo][slotType] === undefined) {
this[registerTo][slotType] = { nodes: [] };
}
if (!this[registerTo][slotType].nodes.includes(class_type)) {
this[registerTo][slotType].nodes.push(class_type);
}
// check if is a new type
if (!out){
if (!this.slot_types_in.includes(sT.toLowerCase())){
this.slot_types_in.push(sT.toLowerCase());
if (!out) {
if (!this.slot_types_in.includes(slotType.toLowerCase())) {
this.slot_types_in.push(slotType.toLowerCase());
this.slot_types_in.sort();
}
}else{
if (!this.slot_types_out.includes(sT.toLowerCase())){
this.slot_types_out.push(sT.toLowerCase());
} else {
if (!this.slot_types_out.includes(slotType.toLowerCase())) {
this.slot_types_out.push(slotType.toLowerCase());
this.slot_types_out.sort();
}
}

View File

@@ -1,12 +1,17 @@
describe("register node types", () => {
let lg;
let calc_sum;
let Sum;
beforeEach(() => {
jest.resetModules();
lg = require("./litegraph");
calc_sum = function calc_sum(a, b) {
return a + b;
Sum = function Sum() {
this.addInput("a", "number");
this.addInput("b", "number");
this.addOutput("sum", "number");
};
Sum.prototype.onExecute = function (a, b) {
this.setOutputData(0, a + b);
};
});
@@ -15,12 +20,12 @@ describe("register node types", () => {
});
test("normal case", () => {
lg.LiteGraph.registerNodeType("math/sum", calc_sum);
lg.LiteGraph.registerNodeType("math/sum", Sum);
let node = lg.LiteGraph.registered_node_types["math/sum"];
expect(node).toBeTruthy();
expect(node.type).toBe("math/sum");
expect(node.title).toBe("calc_sum");
expect(node.title).toBe("Sum");
expect(node.category).toBe("math");
expect(node.prototype.configure).toBe(
lg.LGraphNode.prototype.configure
@@ -34,10 +39,10 @@ describe("register node types", () => {
lg.LiteGraph.onNodeTypeRegistered = jest.fn();
lg.LiteGraph.onNodeTypeReplaced = jest.fn();
lg.LiteGraph.registerNodeType("math/sum", calc_sum);
lg.LiteGraph.registerNodeType("math/sum", Sum);
expect(lg.LiteGraph.onNodeTypeRegistered).toHaveBeenCalled();
expect(lg.LiteGraph.onNodeTypeReplaced).not.toHaveBeenCalled();
lg.LiteGraph.registerNodeType("math/sum", calc_sum);
lg.LiteGraph.registerNodeType("math/sum", Sum);
expect(lg.LiteGraph.onNodeTypeReplaced).toHaveBeenCalled();
expect(consoleSpy).toHaveBeenCalledWith(
expect.stringMatching("replacing node type")
@@ -48,8 +53,8 @@ describe("register node types", () => {
});
test("node with title", () => {
calc_sum.title = "The sum title";
lg.LiteGraph.registerNodeType("math/sum", calc_sum);
Sum.title = "The sum title";
lg.LiteGraph.registerNodeType("math/sum", Sum);
let node = lg.LiteGraph.registered_node_types["math/sum"];
expect(node.title).toBe("The sum title");
expect(node.title).not.toBe(node.name);
@@ -62,7 +67,7 @@ describe("register node types", () => {
});
test("check shape mapping", () => {
lg.LiteGraph.registerNodeType("math/sum", calc_sum);
lg.LiteGraph.registerNodeType("math/sum", Sum);
const node_type = lg.LiteGraph.registered_node_types["math/sum"];
expect(new node_type().shape).toBe(undefined);
@@ -81,10 +86,10 @@ describe("register node types", () => {
// Check that also works for replaced node types
jest.spyOn(console, "log").mockImplementation(() => {});
function new_calc_sum(a, b) {
function NewCalcSum(a, b) {
return a + b;
}
lg.LiteGraph.registerNodeType("math/sum", new_calc_sum);
lg.LiteGraph.registerNodeType("math/sum", NewCalcSum);
const new_node_type = lg.LiteGraph.registered_node_types["math/sum"];
new_node_type.prototype.shape = "box";
expect(new new_node_type().shape).toBe(lg.LiteGraph.BOX_SHAPE);
@@ -95,8 +100,8 @@ describe("register node types", () => {
.spyOn(console, "warn")
.mockImplementation(() => {});
calc_sum.prototype.onPropertyChange = true;
lg.LiteGraph.registerNodeType("math/sum", calc_sum);
Sum.prototype.onPropertyChange = true;
lg.LiteGraph.registerNodeType("math/sum", Sum);
expect(consoleSpy).toBeCalledTimes(1);
expect(consoleSpy).toBeCalledWith(
expect.stringContaining("has onPropertyChange method")
@@ -108,13 +113,18 @@ describe("register node types", () => {
expect(lg.LiteGraph.node_types_by_file_extension).toEqual({});
// Create two node types with calc_times overriding .pdf
calc_sum.supported_extensions = ["PDF", "exe", null];
function calc_times(a, b) {
return a * b;
Sum.supported_extensions = ["PDF", "exe", null];
function Times() {
this.addInput("a", "number");
this.addInput("b", "number");
this.addOutput("times", "number");
}
calc_times.supported_extensions = ["pdf", "jpg"];
lg.LiteGraph.registerNodeType("math/sum", calc_sum);
lg.LiteGraph.registerNodeType("math/times", calc_times);
Times.prototype.onExecute = function (a, b) {
this.setOutputData(0, a * b);
};
Times.supported_extensions = ["pdf", "jpg"];
lg.LiteGraph.registerNodeType("math/sum", Sum);
lg.LiteGraph.registerNodeType("math/times", Times);
expect(
Object.keys(lg.LiteGraph.node_types_by_file_extension).length
@@ -123,8 +133,94 @@ describe("register node types", () => {
expect(lg.LiteGraph.node_types_by_file_extension).toHaveProperty("exe");
expect(lg.LiteGraph.node_types_by_file_extension).toHaveProperty("jpg");
expect(lg.LiteGraph.node_types_by_file_extension.exe).toBe(calc_sum);
expect(lg.LiteGraph.node_types_by_file_extension.pdf).toBe(calc_times);
expect(lg.LiteGraph.node_types_by_file_extension.jpg).toBe(calc_times);
expect(lg.LiteGraph.node_types_by_file_extension.exe).toBe(Sum);
expect(lg.LiteGraph.node_types_by_file_extension.pdf).toBe(Times);
expect(lg.LiteGraph.node_types_by_file_extension.jpg).toBe(Times);
});
test("register in/out slot types", () => {
expect(lg.LiteGraph.registered_slot_in_types).toEqual({});
expect(lg.LiteGraph.registered_slot_out_types).toEqual({});
// Test slot type registration with first type
lg.LiteGraph.auto_load_slot_types = true;
lg.LiteGraph.registerNodeType("math/sum", Sum);
expect(lg.LiteGraph.registered_slot_in_types).toEqual({
number: { nodes: ["math/sum"] },
});
expect(lg.LiteGraph.registered_slot_out_types).toEqual({
number: { nodes: ["math/sum"] },
});
// Test slot type registration with second type
function ToInt() {
this.addInput("string", "string");
this.addOutput("number", "number");
};
ToInt.prototype.onExecute = function (str) {
this.setOutputData(0, Number(str));
};
lg.LiteGraph.registerNodeType("basic/to_int", ToInt);
expect(lg.LiteGraph.registered_slot_in_types).toEqual({
number: { nodes: ["math/sum"] },
string: { nodes: ["basic/to_int"] },
});
expect(lg.LiteGraph.registered_slot_out_types).toEqual({
number: { nodes: ["math/sum", "basic/to_int"] },
});
});
});
describe("unregister node types", () => {
let lg;
let Sum;
beforeEach(() => {
jest.resetModules();
lg = require("./litegraph");
Sum = function Sum() {
this.addInput("a", "number");
this.addInput("b", "number");
this.addOutput("sum", "number");
};
Sum.prototype.onExecute = function (a, b) {
this.setOutputData(0, a + b);
};
});
afterEach(() => {
jest.restoreAllMocks();
});
test("remove by name", () => {
lg.LiteGraph.registerNodeType("math/sum", Sum);
expect(lg.LiteGraph.registered_node_types["math/sum"]).toBeTruthy();
lg.LiteGraph.unregisterNodeType("math/sum");
expect(lg.LiteGraph.registered_node_types["math/sum"]).toBeFalsy();
});
test("remove by object", () => {
lg.LiteGraph.registerNodeType("math/sum", Sum);
expect(lg.LiteGraph.registered_node_types["math/sum"]).toBeTruthy();
lg.LiteGraph.unregisterNodeType(Sum);
expect(lg.LiteGraph.registered_node_types["math/sum"]).toBeFalsy();
});
test("try removing with wrong name", () => {
expect(() => lg.LiteGraph.unregisterNodeType("missing/type")).toThrow(
"node type not found: missing/type"
);
});
test("no constructor name", () => {
function BlankNode() {}
BlankNode.constructor = {}
lg.LiteGraph.registerNodeType("blank/node", BlankNode);
expect(lg.LiteGraph.registered_node_types["blank/node"]).toBeTruthy()
lg.LiteGraph.unregisterNodeType("blank/node");
expect(lg.LiteGraph.registered_node_types["blank/node"]).toBeFalsy();
})
});

16
utils/test.sh Executable file
View File

@@ -0,0 +1,16 @@
#!/bin/bash
set -eo pipefail
cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
export NVM_DIR=$HOME/.nvm
source "$NVM_DIR/nvm.sh"
# This are versions 12, 14, 16, 18
NODE_VERSIONS=("lts/erbium" "lts/fermium" "lts/gallium" "lts/hydrogen")
for NODE_VERSION in "${NODE_VERSIONS[@]}"; do
nvm install "$NODE_VERSION"
nvm exec "$NODE_VERSION" npm install
nvm exec "$NODE_VERSION" npm test
done