Skip to content

Octave: dotted feval in DashboardWidgetRegistry.fromStruct breaks widget deserialization (dashboard load + detach) #371

Description

@HanSur94

Summary

DashboardWidgetRegistry.fromStruct deserializes widgets with a dotted-static-method feval:

% libs/Dashboard/DashboardWidgetRegistry.m:92
w = feval([className '.fromStruct'], s);

GNU Octave (a fully supported runtime per the project docs) does not resolve that form and throws:

feval: function 'FastSenseWidget.fromStruct' not found

MATLAB is unaffected.

Impact

Both code paths that deserialize a widget are broken under Octave:

  1. Serialized dashboard loadDashboardEngine.load(jsonPath) / any fromStruct round-trip.
  2. Detached mirrorsDashboardEngine.detachWidgetDetachedMirror.cloneWidget (libs/Dashboard/DetachedMirror.m:178) → the registry call above.

Programmatically-built dashboards (addWidget + render) work under Octave; only deserialization/detach hit this.

Reproduce (Octave 11)

install();
bx = linspace(0,1000,5000);
t1 = SensorTag('a','X',bx,'Y',sin(bx/7));
d  = DashboardEngine('Repro');
d.addWidget('fastsense','Title','A','Position',[1,1,12,2],'Tag',t1);
d.render();
d.detachWidget(d.activePageWidgets(){1});   % -> feval: function 'FastSenseWidget.fromStruct' not found

Suggested fix

Replace the string-concatenation feval with a handle Octave resolves:

fn = str2func([className '.fromStruct']);
w  = fn(s);

Verify str2func([className '.fromStruct']) actually resolves a static-method handle in Octave (test in Octave 11); if it doesn't, fall back to another portable dispatch (e.g. metaclass lookup). Confirm the fix in both MATLAB R2025b and Octave 11 by round-tripping a widget through toStruct/fromStruct and by exercising detachWidget, and run the widget-serialization / DashboardSerializer suites on both runtimes.

Context

Found while adding benchmarks/bench_detached_mirror_refresh.m (merged in #215), which currently guards with an Octave skip because of this. Once fixed, that skip can be removed. See the note in benchmarks/.reports/coverage.md.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions