From 4636367de2cbfebe18587e6670a9ddbe68fc3789 Mon Sep 17 00:00:00 2001 From: filtered <176114999+webfiltered@users.noreply.github.com> Date: Wed, 26 Feb 2025 04:19:27 +1100 Subject: [PATCH] [TS] Use strict mode in LGraphNode - initial (#598) - Part of effort to convert LGraphNode to TS strict - Adds some small runtime changes - no impact expected, but it is possible - Runtime changes are in separate commits from compile-time type changes - Risk of downstream impact is low --- src/ContextMenu.ts | 2 +- src/LGraph.ts | 9 ++++++--- src/LGraphNode.ts | 39 ++++++++++++++++++++++---------------- src/LiteGraphGlobal.ts | 6 +++--- src/interfaces.ts | 6 ++++++ src/litegraph.ts | 2 +- src/types/serialisation.ts | 2 +- 7 files changed, 41 insertions(+), 25 deletions(-) diff --git a/src/ContextMenu.ts b/src/ContextMenu.ts index ed0ac3bd4..626f50d84 100644 --- a/src/ContextMenu.ts +++ b/src/ContextMenu.ts @@ -35,7 +35,7 @@ export class ContextMenu { * - ignore_item_callbacks: ignores the callback inside the item, it just calls the options.callback * - event: you can pass a MouseEvent, this way the ContextMenu appears in that position */ - constructor(values: (IContextMenuValue | string)[], options: IContextMenuOptions) { + constructor(values: (IContextMenuValue | string | null)[], options: IContextMenuOptions) { options ||= {} this.options = options diff --git a/src/LGraph.ts b/src/LGraph.ts index 1c5668831..47e4fcf6d 100644 --- a/src/LGraph.ts +++ b/src/LGraph.ts @@ -206,7 +206,7 @@ export class LGraph implements LinkNetwork, Serialisable { onGetNodeMenuOptions?(options: IContextMenuValue[], node: LGraphNode): void onNodeConnectionChange?( nodeSlotType: ISlotType, - targetNode: LGraphNode, + targetNode: LGraphNode | null | undefined, slotIndex: number, sourceNode?: LGraphNode, sourceSlotIndex?: number, @@ -570,8 +570,11 @@ export class LGraph implements LinkNetwork, Serialisable { continue } - if (set_level && (!target_node._level || target_node._level <= node._level)) { - target_node._level = node._level + 1 + if (set_level) { + node._level ??= 0 + if (!target_node._level || target_node._level <= node._level) { + target_node._level = node._level + 1 + } } // mark as visited diff --git a/src/LGraphNode.ts b/src/LGraphNode.ts index eb2ee89ea..ab89c9dfe 100644 --- a/src/LGraphNode.ts +++ b/src/LGraphNode.ts @@ -190,7 +190,7 @@ export class LGraphNode implements Positionable, IPinnable, IColorable { // Execution order, automatically computed during run order?: number - mode: LGraphEventMode + mode?: LGraphEventMode last_serialization?: ISerialisedNode serialize_widgets?: boolean /** @@ -221,8 +221,9 @@ export class LGraphNode implements Positionable, IPinnable, IColorable { /** The box color used to render the node. */ get renderingBoxColor(): string { - let colState = LiteGraph.node_box_coloured_by_mode && LiteGraph.NODE_MODES_COLORS[this.mode] - ? LiteGraph.NODE_MODES_COLORS[this.mode] + const mode = this.mode ?? LGraphEventMode.ALWAYS + let colState = LiteGraph.node_box_coloured_by_mode && LiteGraph.NODE_MODES_COLORS[mode] + ? LiteGraph.NODE_MODES_COLORS[mode] : undefined if (LiteGraph.node_box_coloured_when_on) { @@ -255,10 +256,10 @@ export class LGraphNode implements Positionable, IPinnable, IColorable { ) ?? null } - exec_version: number + exec_version?: number action_call?: string - execute_triggered: number - action_triggered: number + execute_triggered?: number + action_triggered?: number widgets_up?: boolean widgets_start_y?: number lostFocusAt?: number @@ -271,11 +272,11 @@ export class LGraphNode implements Positionable, IPinnable, IColorable { * The width of the node when collapsed. * Updated by {@link LGraphCanvas.drawNode} */ - _collapsed_width: number + _collapsed_width?: number /** Called once at the start of every frame. Caller may change the values in {@link out}, which will be reflected in {@link boundingRect}. */ onBounding?(this: LGraphNode, out: Rect): void console?: string[] - _level: number + _level?: number _shape?: RenderShape mouseOver?: IMouseOverData redraw_on_mouse?: boolean @@ -345,7 +346,7 @@ export class LGraphNode implements Positionable, IPinnable, IColorable { return this.flags.collapsed ? [this._collapsed_width, 0] : this._size } - get shape(): RenderShape { + get shape(): RenderShape | undefined { return this._shape } @@ -378,7 +379,7 @@ export class LGraphNode implements Positionable, IPinnable, IColorable { return this._shape || this.constructor.shape || LiteGraph.NODE_DEFAULT_SHAPE } - public get is_selected(): boolean { + public get is_selected(): boolean | undefined { return this.selected } @@ -421,7 +422,7 @@ export class LGraphNode implements Positionable, IPinnable, IColorable { type: ISlotType, index: number, isConnected: boolean, - link_info: LLink, + link_info: LLink | null | undefined, inputOrOutput: INodeInputSlot | INodeOutputSlot, ): void onInputAdded?(this: LGraphNode, input: INodeInputSlot): void @@ -513,8 +514,8 @@ export class LGraphNode implements Positionable, IPinnable, IColorable { onOutputDblClick?(this: LGraphNode, index: number, e: CanvasMouseEvent): void // TODO: Return type onGetPropertyInfo?(this: LGraphNode, property: string): any - onNodeOutputAdd?(this: LGraphNode, value): void - onNodeInputAdd?(this: LGraphNode, value): void + onNodeOutputAdd?(this: LGraphNode, value: unknown): void + onNodeInputAdd?(this: LGraphNode, value: unknown): void onMenuNodeInputs?( this: LGraphNode, entries: IOptionalSlotData[], @@ -612,17 +613,22 @@ export class LGraphNode implements Positionable, IPinnable, IColorable { continue } + // @ts-ignore #594 if (info[j] == null) { continue + // @ts-ignore #594 } else if (typeof info[j] == "object") { - // object + // @ts-ignore #594 if (this[j]?.configure) { + // @ts-ignore #594 this[j]?.configure(info[j]) } else { + // @ts-ignore #594 this[j] = LiteGraph.cloneObject(info[j], this[j]) } } else { // value + // @ts-ignore #594 this[j] = info[j] } } @@ -711,6 +717,7 @@ export class LGraphNode implements Positionable, IPinnable, IColorable { if (this.widgets[i]) o.widgets_values[i] = this.widgets[i].value else + // @ts-ignore #595 No-null o.widgets_values[i] = null } } @@ -728,7 +735,7 @@ export class LGraphNode implements Positionable, IPinnable, IColorable { } /* Creates a clone of this node */ - clone(): LGraphNode { + clone(): LGraphNode | null { const node = LiteGraph.createNode(this.type) if (!node) return null @@ -3049,7 +3056,7 @@ export class LGraphNode implements Positionable, IPinnable, IColorable { * @returns `true` if any new links were established, otherwise `false`. * @todo Decision: Change API to return array of new links instead? */ - connectInputToOutput(): boolean { + connectInputToOutput(): boolean | undefined { const { inputs, outputs, graph } = this if (!inputs || !outputs) return diff --git a/src/LiteGraphGlobal.ts b/src/LiteGraphGlobal.ts index b251bc605..2a5747ab3 100644 --- a/src/LiteGraphGlobal.ts +++ b/src/LiteGraphGlobal.ts @@ -15,7 +15,7 @@ import { } from "./types/globalEnums" import { LGraphNode } from "./LGraphNode" import { SlotShape, SlotDirection, SlotType, LabelPosition } from "./draw" -import type { Dictionary, ISlotType, Rect } from "./interfaces" +import type { Dictionary, ISlotType, Rect, WhenNullish } from "./interfaces" import { distance, isInsideRectangle, overlapBounding } from "./measure" import { Reroute } from "./Reroute" @@ -563,8 +563,8 @@ export class LiteGraphGlobal { // separated just to improve if it doesn't work /** @deprecated Prefer {@link structuredClone} */ - cloneObject(obj: T, target?: T): T | null { - if (obj == null) return null + cloneObject(obj: T, target?: T): WhenNullish { + if (obj == null) return null as WhenNullish const r = JSON.parse(JSON.stringify(obj)) if (!target) return r diff --git a/src/interfaces.ts b/src/interfaces.ts index 2af796647..324614763 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -13,6 +13,12 @@ export type NullableProperties = { [P in keyof T]: T[P] | null } +/** + * If {@link T} is `null` or `undefined`, evaluates to {@link Result}. Otherwise, evaluates to {@link T}. + * Useful for functions that return e.g. `undefined` when a param is nullish. + */ +export type WhenNullish = T & {} | (T extends null ? Result : T extends undefined ? Result : T & {}) + export type CanvasColour = string | CanvasGradient | CanvasPattern /** An object containing a set of child objects */ diff --git a/src/litegraph.ts b/src/litegraph.ts index 1e7bd3688..ac8913bf8 100644 --- a/src/litegraph.ts +++ b/src/litegraph.ts @@ -143,7 +143,7 @@ export interface LiteGraphCanvasEvent extends CustomEvent {} /** https://github.com/jagenjo/litegraph.js/blob/master/guides/README.md#lgraphnode */ export interface LGraphNodeConstructor { - title?: string + title: string type?: string size?: Size min_height?: number diff --git a/src/types/serialisation.ts b/src/types/serialisation.ts index 37b223ffd..615f551b0 100644 --- a/src/types/serialisation.ts +++ b/src/types/serialisation.ts @@ -91,7 +91,7 @@ export interface ISerialisedGroup { id: number title: string bounding: number[] - color: string + color?: string font_size: number flags?: IGraphGroupFlags }