Metadata
- Source
- FLUID-6741
- Type
- Bug
- Priority
- Major
- Status
- Closed
- Resolution
- Fixed
- Assignee
- Antranig Basman
- Reporter
- Antranig Basman
- Created
2022-06-30T09:46:25.863-0400 - Updated
2024-07-22T10:35:17.658-0400 - Versions
-
- 4.1
- Fixed Versions
-
- 4.2
- Component
-
- Framework
Description
Encountered as a bare failure in https://github.com/continuing-creativity/youme/pull/2#issuecomment-1170977935 where a component "connection" is lensed from an asynchronous resource. The failure is
TypeError: Cannot read properties of undefined (reading 'initModelTransactionId')
at fluid.enlistModelComponent (http://localhost:7357/node_modules/infusion/dist/infusion-all.js:148:122208)
at fluid.establishModelRelay (http://localhost:7357/node_modules/infusion/dist/infusion-all.js:148:146922)
at fluid.expander.invokeFunc [as typeFunc] (http://localhost:7357/node_modules/infusion/dist/infusion-all.js:148:116302)
at fluid.expandImmediateImpl (http://localhost:7357/node_modules/infusion/dist/infusion-all.js:148:113546)
at fluid.expandImmediate (http://localhost:7357/node_modules/infusion/dist/infusion-all.js:148:113301)
at fluid.memberFromRecord (http://localhost:7357/node_modules/infusion/dist/infusion-all.js:148:26913)
at Array.strategy (http://localhost:7357/node_modules/infusion/dist/infusion-all.js:148:28140)
at fluid.model.traverseWithStrategy (http://localhost:7357/node_modules/infusion/dist/infusion-all.js:148:117256)
at fluid.model.accessImpl (http://localhost:7357/node_modules/infusion/dist/infusion-all.js:139:15457)
at fluid.model.accessWithStrategy (http://localhost:7357/node_modules/infusion/dist/infusion-all.js:148:118497)
What has happened is that the 3rd component in the transaction, "connection", begins at workflow level 0, "enlistModelComponent" as a result of having its model resource resolve, and since this workflow stage is not marked as "waitIO", the current tree transaction is not restored.
Perhaps this is a good opportunity to eliminate the confusing and probably unperformant heavily promise-based implementation of the workflow system in favour of a priority queue, perhaps the one at https://stackoverflow.com/a/42919752
Something is odd, however, since this seems like exactly the case covered by the FLUID-6390 test https://github.com/fluid-project/infusion/blob/main/tests/framework-tests/core/js/DataBindingTests.js#L1204-L1226 which lenses a tree of components from a resource-backed model, but perhaps the difference is that there is one level of "firebreak" in that the top level of tree containment "levels" is static.
Comments
-
Antranig Basman commented
2022-07-01T09:21:47.507-0400 It looks like this failure is due to the strategy of converting between "ports" and "connectionPort" via a programmatic modelListener which then fires a manual model change - this is something we would do more routinely in "old Infusion" (of the 2.x-3.x era) but prefer to do more declaratively via relays. I verified the issue with a test case looking as so:
fluid.defaults("fluid.tests.fluid6741connector", { gradeNames: ["fluid.modelComponent", "fluid.resourceLoader"], model: { connectionPort: null, ports: "{that}.resources.resourceSource.parsed" }, resources: { resourceSource: { promiseFunc: "fluid.tests.resolveLater", promiseArgs: [[1, 2, 3]] } }, dynamicComponents: { connection: { type: "fluid.modelComponent", source: "{that}.model.connectionPort" } }, modelListeners: { ports: { funcName: "fluid.tests.fluid6741findPort", args: "{that}" } } }); fluid.tests.fluid6741findPort = function (that) { that.applier.change("connectionPort", that.model.ports[0]); }; jqUnit.asyncTest("FLUID-6741: Lensed components via resource and model listener", function () { var that = fluid.tests.fluid6741connector(); that.events.onCreate.then(function () { jqUnit.assertValue("Lensed component should have been constructed", that.connection); jqUnit.start(); }); });
but found that if we axe the modelListener in favour of a more idiomatic modelRelay definition like so:
modelRelay: { portsToconnectionPort: { target: "connectionPort", source: "ports", func: ports => ports[0] } }
The instantiation error goes away. However, the headline issue should still be fixed.
-
Tony Atkins commented
2022-07-01T10:57:41.611-0400 Is there an example somewhere that uses a modelRelay with the` func` property? I didn't see anything in the docs.
Also, idiomatic or not, the model relay pattern might not be a good fit for all cases. I only want to pass on the information if conditions are met, i.e. if there is a match among ports for what I would like to connect to. I haven't seen anything about conditional model relays thus far.
-
Tony Atkins commented
2022-07-01T13:02:24.700-0400 I suspect that if I understand what you meant by
func
(singleTransform
?), I can use what I have and simply return the value to be set as part of a relay instead of trying to apply the change myself. -
Antranig Basman commented
2022-07-03T05:07:37.783-0400 Yes, that's right, your existing function is admirably suited to being packaged as a simpler and more functional relay rule. If there is no match amongst ports it can simply return undefined or an empty array. Thanks for the ping about docs, I've added a catch-all docs JIRA https://issues.fluidproject.org/browse/FLUID-6743 for things we need to catch up on. Short-form model relay tests are at https://github.com/fluid-project/infusion/blob/main/tests/framework-tests/core/js/DataBindingTests.js#L1444-L1542