stonyx 0.2.3-alpha.57 → 0.2.3-alpha.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/modules.js +52 -7
- package/package.json +1 -1
package/dist/modules.js
CHANGED
|
@@ -18,8 +18,24 @@ function configureLog(chronicle, module, config) {
|
|
|
18
18
|
function initializeModule(moduleName, moduleClass, modules, initPromises) {
|
|
19
19
|
const moduleInstance = new moduleClass();
|
|
20
20
|
modules.push(moduleInstance);
|
|
21
|
-
|
|
21
|
+
// A module class with no `init()` has nothing to initialise, so it is ready
|
|
22
|
+
// the moment it is instantiated. Without this its registered promise dangles
|
|
23
|
+
// — the only resolve on this path lives inside the `init()` wrapper below,
|
|
24
|
+
// which is never created. Third of the three never-resolved paths named in
|
|
25
|
+
// #120, and the one that scoping registration to `discovered` does NOT close,
|
|
26
|
+
// because such a module IS discovered — measured, not reasoned: with only
|
|
27
|
+
// the registration fix applied the suite read 180/1 with T24 the sole
|
|
28
|
+
// failure. Resolving here is truthful, because the module really did load,
|
|
29
|
+
// and that is what separates it from resolving on a discovery `continue`,
|
|
30
|
+
// where there is no module to be ready.
|
|
31
|
+
//
|
|
32
|
+
// `?.` for the reason the resolve below carries it: `initializeModule` is
|
|
33
|
+
// also reached from the standalone path as `initializeModule(projectName, …)`,
|
|
34
|
+
// and `projectName` is never a key in `modulePromises`.
|
|
35
|
+
if (!moduleInstance.init) {
|
|
36
|
+
modulePromises[moduleName]?.resolve();
|
|
22
37
|
return;
|
|
38
|
+
}
|
|
23
39
|
initPromises.push((async () => {
|
|
24
40
|
await moduleInstance.init();
|
|
25
41
|
modulePromises[moduleName]?.resolve();
|
|
@@ -107,12 +123,6 @@ export default async function loadModules(config, rootPath, chronicle) {
|
|
|
107
123
|
// unresolved. T3 owns that kill. What is a module is decided below, by the
|
|
108
124
|
// `stonyx-module` keyword; this is only a name test that bounds the scan.
|
|
109
125
|
const moduleDependencies = Object.keys(declaredDependencies).filter((moduleName) => moduleName.startsWith('@stonyx/'));
|
|
110
|
-
// Setup module promises prior to initialization
|
|
111
|
-
for (const moduleName of moduleDependencies) {
|
|
112
|
-
const promise = {};
|
|
113
|
-
modulePromises[moduleName] = promise;
|
|
114
|
-
promise.ready = new Promise(resolve => promise.resolve = resolve);
|
|
115
|
-
}
|
|
116
126
|
// DISCOVERY, hoisted above the pre-flight.
|
|
117
127
|
//
|
|
118
128
|
// The pre-flight must check exactly what the loader loads, and no more.
|
|
@@ -143,6 +153,41 @@ export default async function loadModules(config, rootPath, chronicle) {
|
|
|
143
153
|
keywords,
|
|
144
154
|
});
|
|
145
155
|
}
|
|
156
|
+
// Setup module promises prior to initialization — over `discovered`, NOT
|
|
157
|
+
// over `moduleDependencies`.
|
|
158
|
+
//
|
|
159
|
+
// This loop used to run above discovery and consume the declared list. That
|
|
160
|
+
// was already the shape at base, but rule 3 widened what the declared list
|
|
161
|
+
// contains, and the widening turned a fast named throw into an unbounded
|
|
162
|
+
// boot hang. A name registered here but never resolved leaves
|
|
163
|
+
// `waitForModule` pending forever; discovery `continue`s past two kinds of
|
|
164
|
+
// name without reaching either of this file's two resolve sites — a manifest
|
|
165
|
+
// that is not there, and a package without the `stonyx-module` keyword.
|
|
166
|
+
// `@stonyx/logs` ships without that keyword and is an ordinary `dependencies`
|
|
167
|
+
// entry, so this is a shape the fleet actually has.
|
|
168
|
+
//
|
|
169
|
+
// name in `dependencies`, not installed, another module awaits it
|
|
170
|
+
// base 5693744 throws "…was not registered in project dependencies", 3 ms
|
|
171
|
+
// a57045e one console.warn, then loadModules never settles
|
|
172
|
+
//
|
|
173
|
+
// Registering only what discovery admitted restores the fail-fast for both,
|
|
174
|
+
// and for `devDependencies`-declared names too — that half is INHERITED, not
|
|
175
|
+
// introduced here, and it is a real behaviour change: hang becomes throw.
|
|
176
|
+
// T13 pins it, and the PR body names it.
|
|
177
|
+
//
|
|
178
|
+
// The alternative — resolving in each `continue` branch — also removes the
|
|
179
|
+
// hang and is worse: `waitForModule` would report success for a module that
|
|
180
|
+
// was never loaded, silently. T23 asserts the named rejection precisely so
|
|
181
|
+
// that remedy cannot pass.
|
|
182
|
+
//
|
|
183
|
+
// Ordering is safe: nothing between here and the old site touches
|
|
184
|
+
// `modulePromises`, discovery only reads manifests, and registration still
|
|
185
|
+
// completes before the first `init()` can run.
|
|
186
|
+
for (const { name: moduleName } of discovered) {
|
|
187
|
+
const promise = {};
|
|
188
|
+
modulePromises[moduleName] = promise;
|
|
189
|
+
promise.ready = new Promise(resolve => promise.resolve = resolve);
|
|
190
|
+
}
|
|
146
191
|
// Pre-flight: invariant I1, "one core". Before ANY module entry point is
|
|
147
192
|
// imported, because the point of the check is the module that would NOT
|
|
148
193
|
// throw — it would load, initialise, and register its hooks on a second
|