FLUID-6744: Undefined options value causes corruption in options merging

Metadata

Source
FLUID-6744
Type
Bug
Priority
Major
Status
Closed
Resolution
Fixed
Assignee
Antranig Basman
Reporter
Antranig Basman
Created
2022-07-07T07:29:54.686-0400
Updated
2024-07-17T08:03:27.338-0400
Versions
  1. 4.2
Fixed Versions
  1. 4.3
Component
  1. Framework

Description

Ordinarily it is not possible for a component's options to hold the value undefined but this can be achieved when sourcing subcomponent options wholesale from an undefined source, e.g.

dynamicComponents: {
        enactors: {
            sources: "{uiEnhancer}.options.enactorRegistry",
            type: "{source}.type",
            options: "{source}.options"
        }
    },

This ends up falling foul of a faulty optimisation written very early into the 2011-era options merging pipeline:

function regenerateSources(sources, segs, limit, sourceStrategies) {
    var togo = [];
    for (var i = 0; i < sources.length; ++i) {
        var thisSource = regenerateCursor(sources[i], segs, limit, sourceStrategies[i]);
        if (thisSource !== undefined) {
            togo.push(thisSource);
        }
    }
    return togo;
}

This produces a "sources" array one shorter than the original strategies array and ensure that the last options distribution, whatever it is, will be lost.

For example, with multiple options distributions targetting "gradeNames".

What we have tried to write is

fluid.defaults("fluid.prefs.moduleSyllabificationPattern", {
    gradeNames: "fluid.component",
    // This value and mechanism should become the default
    modulePatternPrefix: "%fluid-infusion/lib/hypher/patterns",
    terms: {
        patternPrefix: "@expand:fluid.resourceLoader.rewritePath({that}.options.modulePatternPrefix)",
    }
});fluid.makeGradeLinkage("fluid.prefs.moduleSyllabificationPatternDistributor", 
    ["fluid.prefs.enactor.syllabification.patterns"], "fluid.prefs.moduleSyllabificationPattern");

targetting

fluid.defaults("fluid.prefs.enactor.syllabification.patterns", {
    terms: {
        patternPrefix: "../../../lib/hypher/patterns"
    },
    patterns: {
        be: "%patternPrefix/bg.js",
 ...

but note that the "patterns" is plastered onto the enactor itself with

fluid.defaults("fluid.prefs.enactor.syllabification", {
    gradeNames: ["fluid.prefs.enactor", "fluid.prefs.enactor.syllabification.patterns", "fluid.viewComponent"], 
....

and that in the Infusion 5 prefs framework we have

fluid.defaults("fluid.prefs.enactor", {
    gradeNames: ["fluid.modelComponent", "fluid.prefs.withPreferencesMap"],
    prefsMapVariety: "enactor"
});

but which we at the same time distributed in via

weaveEnactors: {
            target: "{that fluid.prefs.enactor}.options.gradeNames",
            record: "fluid.prefs.withPreferencesMap"
        }

We found that due to the mutation-fest in fluid.makeMergeStrategy that the expanded "targets" were off by one after the first one targetting gradeNames. This can't really be economically resolved until we axe the whole options merging pipeline and go towards an immutable mat-based system for Infusion 6.

Comments