fix: all hooks are orderable

This commit is contained in:
cha0s 2024-02-16 19:17:52 -06:00
parent ed73e3a8f3
commit e4a3a912cd
2 changed files with 20 additions and 31 deletions

View File

@ -62,10 +62,10 @@ class Flecks {
config = {}; config = {};
$$expandedFlecksCache = {};
flecks = {}; flecks = {};
$$flecksImplementingCache = {};
$$gathered = {}; $$gathered = {};
hooks = {}; hooks = {};
@ -254,7 +254,7 @@ class Flecks {
* Destroy this instance. * Destroy this instance.
*/ */
destroy() { destroy() {
this.$$expandedFlecksCache = {}; this.$$flecksImplementingCache = {};
this.config = {}; this.config = {};
this.$$gathered = {}; this.$$gathered = {};
this.hooks = {}; this.hooks = {};
@ -314,9 +314,9 @@ class Flecks {
* @param {string} hook * @param {string} hook
* @returns {string[]} The expanded list of flecks. * @returns {string[]} The expanded list of flecks.
*/ */
expandedFlecks(hook) { flecksImplementing(hook) {
if (this.$$expandedFlecksCache[hook]) { if (this.$$flecksImplementingCache[hook]) {
return [...this.$$expandedFlecksCache[hook]]; return [...this.$$flecksImplementingCache[hook]];
} }
const flecks = this.lookupFlecks(hook); const flecks = this.lookupFlecks(hook);
let expanded = []; let expanded = [];
@ -338,7 +338,7 @@ class Flecks {
expanded.splice(index, 1); expanded.splice(index, 1);
// Expand elided flecks. // Expand elided flecks.
const elided = []; const elided = [];
const implementing = this.flecksImplementing(hook); const implementing = this.hooks[hook]?.map(({fleck}) => fleck) || [];
for (let i = 0; i < implementing.length; ++i) { for (let i = 0; i < implementing.length; ++i) {
const fleck = implementing[i]; const fleck = implementing[i];
if (!expanded.includes(fleck)) { if (!expanded.includes(fleck)) {
@ -400,10 +400,10 @@ class Flecks {
}); });
} }
// Filter unimplemented. // Filter unimplemented.
this.$$expandedFlecksCache[hook] = expanded // eslint-disable-line no-return-assign this.$$flecksImplementingCache[hook] = expanded // eslint-disable-line no-return-assign
.filter((fleck) => this.fleckImplementation(fleck, hook)); .filter((fleck) => this.fleckImplementation(fleck, hook));
this.constructor.debugSilly("cached hook expansion for '%s': %O", hook, expanded); this.constructor.debugSilly("cached hook expansion for '%s': %O", hook, expanded);
return [...this.$$expandedFlecksCache[hook]]; return [...this.$$flecksImplementingCache[hook]];
} }
/** /**
@ -435,16 +435,6 @@ class Flecks {
return found.fn; return found.fn;
} }
/**
* Get a list of flecks implementing a hook.
*
* @param {string} hook
* @returns {string[]}
*/
flecksImplementing(hook) {
return this.hooks[hook]?.map(({fleck}) => fleck) || [];
}
/** /**
* Create a dependency graph from a list of flecks. * Create a dependency graph from a list of flecks.
* @param {string[]} flecks * @param {string[]} flecks
@ -662,8 +652,7 @@ class Flecks {
if (!this.hooks[hook]) { if (!this.hooks[hook]) {
return initial; return initial;
} }
const flecks = this.expandedFlecks(hook); return this.flecksImplementing(hook)
return flecks
.reduce((r, fleck) => this.invokeFleck(hook, fleck, r, ...args), initial); .reduce((r, fleck) => this.invokeFleck(hook, fleck, r, ...args), initial);
} }
@ -676,8 +665,7 @@ class Flecks {
if (!this.hooks[hook]) { if (!this.hooks[hook]) {
return arg; return arg;
} }
const flecks = this.expandedFlecks(hook); return this.flecksImplementing(hook)
return flecks
.reduce(async (r, fleck) => this.invokeFleck(hook, fleck, await r, ...args), arg); .reduce(async (r, fleck) => this.invokeFleck(hook, fleck, await r, ...args), arg);
} }
@ -692,7 +680,8 @@ class Flecks {
if (!this.hooks[hook]) { if (!this.hooks[hook]) {
return []; return [];
} }
return this.hooks[hook].map(({fleck}) => this.invokeFleck(hook, fleck, ...args)); return this.flecksImplementing(hook)
.map((fleck) => this.invokeFleck(hook, fleck, ...args));
} }
/** /**
@ -831,7 +820,7 @@ class Flecks {
return []; return [];
} }
const results = []; const results = [];
const flecks = this.expandedFlecks(hook); const flecks = this.flecksImplementing(hook);
while (flecks.length > 0) { while (flecks.length > 0) {
const fleck = flecks.shift(); const fleck = flecks.shift();
results.push(this.invokeFleck(hook, fleck, ...args)); results.push(this.invokeFleck(hook, fleck, ...args));
@ -849,7 +838,7 @@ class Flecks {
return []; return [];
} }
const results = []; const results = [];
const flecks = this.expandedFlecks(hook); const flecks = this.flecksImplementing(hook);
while (flecks.length > 0) { while (flecks.length > 0) {
const fleck = flecks.shift(); const fleck = flecks.shift();
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
@ -888,7 +877,7 @@ class Flecks {
if (!this.hooks[hook]) { if (!this.hooks[hook]) {
return (...args) => args.pop()(); return (...args) => args.pop()();
} }
const flecks = this.expandedFlecks(hook); const flecks = this.flecksImplementing(hook);
if (0 === flecks.length) { if (0 === flecks.length) {
// No flecks, immediate dispatch. // No flecks, immediate dispatch.
return (...args) => args.pop()(); return (...args) => args.pop()();

View File

@ -12,7 +12,7 @@ it('includes all by default', async () => {
two: {hooks: {'one.test': () => {}}}, two: {hooks: {'one.test': () => {}}},
}, },
}); });
expect(flecks.expandedFlecks('one.test')) expect(flecks.flecksImplementing('one.test'))
.to.deep.equal(['one', 'two']); .to.deep.equal(['one', 'two']);
}); });
@ -28,7 +28,7 @@ it('respects elision', async () => {
four: {hooks: {'one.test': () => {}}}, four: {hooks: {'one.test': () => {}}},
}, },
}); });
const expanded = flecks.expandedFlecks('one.test'); const expanded = flecks.flecksImplementing('one.test');
expect(expanded.shift()) expect(expanded.shift())
.to.equal('two'); .to.equal('two');
expect(expanded.pop()) expect(expanded.pop())
@ -49,7 +49,7 @@ it('detects yet allows suspicious hook ordering', async () => {
Flecks.debug = (message) => { Flecks.debug = (message) => {
suspected = message.includes('Suspicious ordering specification'); suspected = message.includes('Suspicious ordering specification');
}; };
expect(flecks.expandedFlecks('one.test')) expect(flecks.flecksImplementing('one.test'))
.to.deep.equal(['one', 'two']); .to.deep.equal(['one', 'two']);
expect(suspected) expect(suspected)
.to.be.true; .to.be.true;
@ -62,6 +62,6 @@ it('throws on cyclic dependency', async () => {
two: {hooks: {'one.test': Flecks.priority(() => {}, {before: 'one'})}}, two: {hooks: {'one.test': Flecks.priority(() => {}, {before: 'one'})}},
}, },
}); });
expect(() => flecks.expandedFlecks('one.test')) expect(() => flecks.flecksImplementing('one.test'))
.to.throw(/Illegal ordering specification/); .to.throw(/Illegal ordering specification/);
}); });