@antelopejs/core 1.13.5 → 1.15.0

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.
Files changed (87) hide show
  1. package/dist/core/build/build-artifact.d.ts +3 -1
  2. package/dist/core/build/build-artifact.js.map +1 -1
  3. package/dist/core/config/config-editor.d.ts +8 -0
  4. package/dist/core/config/config-editor.js +227 -0
  5. package/dist/core/config/config-editor.js.map +1 -0
  6. package/dist/core/config/config-loader.d.ts +1 -1
  7. package/dist/core/config/config-loader.js +4 -3
  8. package/dist/core/config/config-loader.js.map +1 -1
  9. package/dist/core/config/config-parser.d.ts +2 -0
  10. package/dist/core/config/config-parser.js +19 -1
  11. package/dist/core/config/config-parser.js.map +1 -1
  12. package/dist/core/config/config-writes.d.ts +2 -0
  13. package/dist/core/config/config-writes.js +24 -0
  14. package/dist/core/config/config-writes.js.map +1 -0
  15. package/dist/core/config/module-declarations.d.ts +4 -0
  16. package/dist/core/config/module-declarations.js +99 -0
  17. package/dist/core/config/module-declarations.js.map +1 -0
  18. package/dist/core/config/module-entry.d.ts +12 -0
  19. package/dist/core/config/module-entry.js +3 -0
  20. package/dist/core/config/module-entry.js.map +1 -0
  21. package/dist/core/embedded/prepare-embedded.js +5 -4
  22. package/dist/core/embedded/prepare-embedded.js.map +1 -1
  23. package/dist/core/embedded/types.d.ts +1 -0
  24. package/dist/core/interface-registry.d.ts +2 -2
  25. package/dist/core/interface-registry.js +19 -12
  26. package/dist/core/interface-registry.js.map +1 -1
  27. package/dist/core/module-isolation.d.ts +18 -0
  28. package/dist/core/module-isolation.js +107 -0
  29. package/dist/core/module-isolation.js.map +1 -0
  30. package/dist/core/module-manager.d.ts +21 -1
  31. package/dist/core/module-manager.js +199 -22
  32. package/dist/core/module-manager.js.map +1 -1
  33. package/dist/core/module-manifest.d.ts +1 -0
  34. package/dist/core/module-manifest.js +34 -0
  35. package/dist/core/module-manifest.js.map +1 -1
  36. package/dist/core/module-registry.d.ts +1 -0
  37. package/dist/core/module-registry.js +3 -0
  38. package/dist/core/module-registry.js.map +1 -1
  39. package/dist/core/module.d.ts +1 -3
  40. package/dist/core/module.js +0 -18
  41. package/dist/core/module.js.map +1 -1
  42. package/dist/core/resolution/binding-diagnostics.d.ts +30 -0
  43. package/dist/core/resolution/binding-diagnostics.js +65 -0
  44. package/dist/core/resolution/binding-diagnostics.js.map +1 -0
  45. package/dist/core/resolution/binding-graph-order.d.ts +3 -0
  46. package/dist/core/resolution/binding-graph-order.js +49 -0
  47. package/dist/core/resolution/binding-graph-order.js.map +1 -0
  48. package/dist/core/resolution/binding-graph-types.d.ts +46 -0
  49. package/dist/core/resolution/binding-graph-types.js +3 -0
  50. package/dist/core/resolution/binding-graph-types.js.map +1 -0
  51. package/dist/core/resolution/binding-graph-warnings.d.ts +11 -0
  52. package/dist/core/resolution/binding-graph-warnings.js +73 -0
  53. package/dist/core/resolution/binding-graph-warnings.js.map +1 -0
  54. package/dist/core/resolution/binding-graph.d.ts +2 -0
  55. package/dist/core/resolution/binding-graph.js +375 -0
  56. package/dist/core/resolution/binding-graph.js.map +1 -0
  57. package/dist/core/resolution/binding-providers.d.ts +11 -0
  58. package/dist/core/resolution/binding-providers.js +47 -0
  59. package/dist/core/resolution/binding-providers.js.map +1 -0
  60. package/dist/core/resolution/instance-copies.d.ts +5 -0
  61. package/dist/core/resolution/instance-copies.js +109 -0
  62. package/dist/core/resolution/instance-copies.js.map +1 -0
  63. package/dist/core/resolution/interface-dependencies.d.ts +1 -0
  64. package/dist/core/resolution/interface-dependencies.js +27 -0
  65. package/dist/core/resolution/interface-dependencies.js.map +1 -0
  66. package/dist/core/resolution/interface-instances.d.ts +28 -0
  67. package/dist/core/resolution/interface-instances.js +188 -0
  68. package/dist/core/resolution/interface-instances.js.map +1 -0
  69. package/dist/core/resolution/resolver-detour.js +14 -22
  70. package/dist/core/resolution/resolver-detour.js.map +1 -1
  71. package/dist/core/resolution/resolver.d.ts +30 -72
  72. package/dist/core/resolution/resolver.js +201 -659
  73. package/dist/core/resolution/resolver.js.map +1 -1
  74. package/dist/core/runtime/build-runtime.d.ts +1 -1
  75. package/dist/core/runtime/build-runtime.js +11 -1
  76. package/dist/core/runtime/build-runtime.js.map +1 -1
  77. package/dist/core/runtime/dev-server-registry.js +1 -1
  78. package/dist/core/runtime/dev-server-registry.js.map +1 -1
  79. package/dist/core/runtime/launch-sequence.js +30 -5
  80. package/dist/core/runtime/launch-sequence.js.map +1 -1
  81. package/dist/core/runtime/module-loading.d.ts +2 -1
  82. package/dist/core/runtime/module-loading.js +88 -26
  83. package/dist/core/runtime/module-loading.js.map +1 -1
  84. package/dist/core/runtime/project-launch.js +13 -2
  85. package/dist/core/runtime/project-launch.js.map +1 -1
  86. package/dist/core/runtime/runtime-types.d.ts +2 -1
  87. package/package.json +3 -3
@@ -1,276 +1,198 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.Resolver = void 0;
4
- const node_util_1 = require("node:util");
5
- const interface_core_1 = require("@antelopejs/interface-core");
7
+ exports.connectionPath = connectionPath;
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const node_fs_1 = require("node:fs");
10
+ const modules_1 = require("@antelopejs/interface-core/modules");
6
11
  const internal_1 = require("@antelopejs/interface-core/internal");
7
12
  const observable_map_1 = require("./observable-map");
8
13
  const package_resolution_1 = require("./package-resolution");
9
14
  const path_owner_index_1 = require("./path-owner-index");
15
+ const interface_instances_1 = require("./interface-instances");
10
16
  const CORE_PKG = "@antelopejs/interface-core";
11
17
  const CORE_PACKAGE = (0, package_resolution_1.resolvePackage)(CORE_PKG, __dirname);
12
18
  const CORE_RESOLVE_FROM = CORE_PACKAGE?.root ?? __dirname;
13
19
  const CORE_ENTRY = CORE_PACKAGE?.entry ?? CORE_PKG;
14
- const SHARED_INTERFACE_OWNER_SUFFIX = "#shared";
15
- const CLASS_PREFIX = "class ";
16
- const PROXY_ATTACHMENT_METHODS = new Set([
17
- "detach",
18
- "onCall",
19
- "onHandlers",
20
- "onRegister",
21
- "onUnregister",
22
- ]);
23
- let nextResolverIdentity = 1;
24
- function isRecognizedInterfaceProxy(value, kind) {
25
- if (node_util_1.types.isProxy(value)) {
26
- return false;
27
- }
28
- if (value instanceof interface_core_1.AsyncProxy ||
29
- value instanceof interface_core_1.EventProxy ||
30
- value instanceof interface_core_1.RegisteringProxy) {
31
- return (0, interface_core_1.IsInterfaceProxy)(value, kind);
32
- }
33
- return isBrandedInterfaceProxy(value, kind);
34
- }
35
- function isBrandedInterfaceProxy(value, kind) {
20
+ const CONNECTION_PREFIX = "@ajs.connection/";
21
+ const INSTANCE_OWNER_SUFFIX = "#instance";
22
+ const RELATIVE_OR_ABSOLUTE = /^(\.{1,2}(\/|\\|$)|\/|[A-Za-z]:[\\/])/;
23
+ function realFolder(folder) {
36
24
  try {
37
- return (0, interface_core_1.IsInterfaceProxy)(value, kind);
25
+ return node_fs_1.realpathSync.native(folder);
38
26
  }
39
27
  catch {
40
- return false;
28
+ return node_path_1.default.resolve(folder);
41
29
  }
42
30
  }
43
- function isPlainContainer(value) {
44
- if (Array.isArray(value)) {
45
- return true;
31
+ function parseConnection(request) {
32
+ if (!request.startsWith(CONNECTION_PREFIX)) {
33
+ return undefined;
46
34
  }
47
- const prototype = Object.getPrototypeOf(value);
48
- return prototype === Object.prototype || prototype === null;
49
- }
50
- function getProxyCandidate(candidate) {
51
- if (typeof candidate === "function" && "proxy" in candidate) {
52
- return candidate.proxy;
35
+ const rest = request.slice(CONNECTION_PREFIX.length);
36
+ const separator = rest.indexOf("/");
37
+ const index = Number(rest.slice(0, separator));
38
+ if (separator < 0 || !Number.isInteger(index)) {
39
+ throw new Error(`Malformed connection path '${request}'.`);
53
40
  }
54
- return candidate;
41
+ return { index, request: rest.slice(separator + 1) };
55
42
  }
56
- function collectProxyReferences(value) {
57
- const references = [];
58
- const visited = new WeakSet();
59
- const visit = (candidate) => {
60
- if ((typeof candidate !== "object" && typeof candidate !== "function") ||
61
- candidate === null) {
62
- return;
63
- }
64
- if (node_util_1.types.isProxy(candidate)) {
65
- return;
66
- }
67
- const proxy = getProxyCandidate(candidate);
68
- if (isRecognizedInterfaceProxy(proxy)) {
69
- const identity = (0, interface_core_1.GetInterfaceProxyIdentity)(proxy);
70
- if (identity) {
71
- references.push({ identity, proxy: proxy });
72
- }
73
- return;
74
- }
75
- if (visited.has(candidate)) {
76
- return;
77
- }
78
- visited.add(candidate);
79
- Object.values(candidate).forEach(visit);
80
- };
81
- visit(value);
82
- return references;
43
+ function connectionPath(index, packageName) {
44
+ return `${CONNECTION_PREFIX}${index}/${packageName}`;
83
45
  }
84
46
  class Resolver {
85
47
  pathMapper;
86
- moduleByFolder = new observable_map_1.ObservableMap(() => this.localModuleOwners.invalidate());
48
+ moduleByFolder = new observable_map_1.ObservableMap(() => this.owners.invalidate());
87
49
  modulesById = new Map();
88
- interfacePackages = new observable_map_1.ObservableMap(() => this.interfacePackageOwners.invalidate());
50
+ interfacePackages = new observable_map_1.ObservableMap(() => this.owners.invalidate());
89
51
  interfacePackageEntries = new Map();
90
52
  interfacePackageResolveFrom = new Map();
91
53
  lifecycleInterfacePackages = new Set();
92
54
  stubbedInterfacePackages = new Set();
93
55
  stubModulePath;
94
- resolverIdentity = nextResolverIdentity++;
95
- localModuleOwners = new path_owner_index_1.PathOwnerIndex(() => this.listModuleRoots());
96
- interfacePackageOwners = new path_owner_index_1.PathOwnerIndex(() => this.listInterfacePackageRoots());
97
- interfaceGraphFiles = new Map();
98
- interfaceDependencies = new Map();
99
- boundValues = new WeakMap();
100
- routedEvents = new Map();
101
- proxyOwners = new Map();
102
- providerlessContexts = new WeakMap();
103
- sharedInterfaceContexts = new WeakMap();
104
- interfaceBodyContexts = new WeakMap();
105
- interfaceBodySharedContexts = new WeakMap();
106
- sharedContexts = new WeakMap();
107
- sharedStubInterfaces = new WeakMap();
108
- adoptedContexts = new WeakMap();
109
- stubbedContexts = new WeakSet();
56
+ instances = new interface_instances_1.InterfaceInstances(() => this.owners.invalidate(), (instance) => this.retireInstance(instance));
57
+ bindings;
58
+ instanceFiles = new Map();
59
+ owners = new path_owner_index_1.PathOwnerIndex(() => this.listOwnerRoots());
110
60
  constructor(pathMapper) {
111
61
  this.pathMapper = pathMapper;
112
62
  }
63
+ setBindings(graph) {
64
+ this.bindings = graph;
65
+ this.instances.update(graph, this.canonicalPackages(), this.fixedRoots());
66
+ }
113
67
  resolve(request, parent) {
114
- const parentModule = this.resolveLocalModule(parent?.filename);
115
- if (parentModule) {
116
- const mapped = this.pathMapper.resolve(request, parentModule.manifest);
68
+ const fileOwner = parent?.filename
69
+ ? this.owners.findOwner(parent.filename)
70
+ : undefined;
71
+ if (fileOwner?.module) {
72
+ const mapped = this.pathMapper.resolve(request, fileOwner.module.manifest);
117
73
  if (mapped) {
118
74
  return { resolvedPath: mapped };
119
75
  }
120
76
  }
121
- const coreResult = this.resolveInterfaceCore(request);
122
- if (coreResult) {
123
- return this.bindResultProvider(coreResult, CORE_PKG, { bindExports: false, sharedExports: false }, parent, parentModule);
124
- }
125
- const interfaceRequest = this.resolveInterfacePackage(request);
126
- if (interfaceRequest) {
127
- this.trackInterfaceDependency(parent?.filename, interfaceRequest.packageName);
128
- return this.bindResultProvider(interfaceRequest.result, interfaceRequest.packageName, {
129
- bindExports: this.interfaceGraphFiles.get(parent?.filename ?? "") !==
130
- interfaceRequest.packageName,
131
- sharedExports: this.isInterfacePackageFile(parent?.filename),
132
- }, parent, parentModule);
77
+ return (this.resolveInterfaceCore(request) ??
78
+ this.resolveInterfaceRequest(request, fileOwner ?? this.contextOwner()));
79
+ }
80
+ locate(result, resolvedPath) {
81
+ if (!result.instance) {
82
+ return resolvedPath;
133
83
  }
134
- return this.resolveRelativeInterface(request, parent, parentModule);
84
+ return this.instances.locate(result.instance, resolvedPath) ?? resolvedPath;
135
85
  }
136
86
  ownsResolutionContext(_request, parent) {
137
87
  const contextModule = (0, internal_1.getModuleContext)()?.module;
138
88
  if (contextModule && this.modulesById.has(contextModule)) {
139
89
  return true;
140
90
  }
141
- return Boolean(this.resolveLocalModule(parent?.filename));
91
+ return Boolean(this.owners.findOwner(parent?.filename ?? ""));
142
92
  }
143
- requiresPreResolution(request, parent) {
144
- return Boolean(this.findRequestedInterface(request, parent?.filename));
145
- }
146
- bindProviderRoutes(result, value) {
147
- const references = collectProxyReferences(value);
148
- if (result.interfaceName) {
149
- this.registerProxyOwners(result.interfaceName, references);
150
- }
151
- const context = (0, internal_1.captureModuleContext)();
152
- if (!context?.providerRoutes) {
153
- return value;
154
- }
155
- this.replayKnownRoutes(context);
156
- if (!result.provider) {
157
- return this.bindStubbedInterfaceValue(result, value, context);
93
+ instanceToLoad(request, parent) {
94
+ const resolved = this.resolve(request, parent)?.instance;
95
+ if (resolved) {
96
+ return resolved;
158
97
  }
159
- this.bindImportedRoutes(context, result, references);
160
- if (!result.bindExports) {
161
- return value;
98
+ if (!RELATIVE_OR_ABSOLUTE.test(request) || !parent?.filename) {
99
+ return undefined;
162
100
  }
163
- return this.bindInterfaceValue(value, this.getBindingContext(result, context));
101
+ return (this.instanceFiles.get(parent.filename) ??
102
+ this.owners.findOwner(parent.filename)?.instance);
103
+ }
104
+ recordInstanceFile(instance, filePath) {
105
+ this.instanceFiles.set(filePath, instance);
164
106
  }
165
- runInInterfaceContext(result, load) {
166
- const context = (0, internal_1.captureModuleContext)();
167
- if (!context || !this.isSharedInterfaceLoad(result)) {
107
+ runInInstance(instance, load) {
108
+ const descriptor = this.instances.describe(instance);
109
+ if (!descriptor ||
110
+ this.lifecycleInterfacePackages.has(descriptor.interfaceName)) {
168
111
  return load();
169
112
  }
170
- return (0, internal_1.runWithCapturedModuleContext)(this.getInterfaceBodyContext(result, context), load);
113
+ const module = (0, internal_1.getModuleContext)()?.module ??
114
+ descriptor.provider ??
115
+ descriptor.interfaceName;
116
+ return (0, internal_1.runWithModuleContext)({ module, owner: `${instance}${INSTANCE_OWNER_SUFFIX}` }, load);
171
117
  }
172
- isSharedInterfaceLoad(result) {
173
- return Boolean(result.interfaceName &&
174
- result.interfaceName !== CORE_PKG &&
175
- result.provider &&
176
- !this.lifecycleInterfacePackages.has(result.interfaceName));
177
- }
178
- trackInterfaceFile(result, resolvedPath) {
179
- if (result.interfaceName) {
180
- this.interfaceGraphFiles.set(resolvedPath, result.interfaceName);
118
+ loadInstance(instance) {
119
+ const root = this.instances.rootOf(instance);
120
+ const entry = this.instanceEntry(instance);
121
+ if (!root || !entry) {
122
+ return undefined;
181
123
  }
124
+ this.runInInstance(instance, () => require(entry));
125
+ return root;
182
126
  }
183
- getInterfaceEntryToPrime(result, resolvedPath) {
184
- const interfaceName = result.interfaceName;
185
- if (!interfaceName || this.lifecycleInterfacePackages.has(interfaceName)) {
127
+ entryToPrime(request, parent, resolvedPath) {
128
+ const instance = this.resolve(request, parent)?.instance;
129
+ const descriptor = instance && this.instances.describe(instance);
130
+ if (!instance ||
131
+ !descriptor ||
132
+ this.lifecycleInterfacePackages.has(descriptor.interfaceName)) {
186
133
  return undefined;
187
134
  }
188
- const entry = this.interfacePackageEntries.get(interfaceName);
189
- if (!entry || entry === resolvedPath || require.cache[entry]) {
135
+ const entry = this.instanceEntry(instance);
136
+ return entry && entry !== resolvedPath && !require.cache[entry]
137
+ ? entry
138
+ : undefined;
139
+ }
140
+ instanceEntry(instance) {
141
+ const name = this.instances.describe(instance)?.interfaceName;
142
+ const canonicalEntry = name
143
+ ? (this.interfacePackageEntries.get(name) ??
144
+ this.interfacePackages.get(name))
145
+ : undefined;
146
+ if (!canonicalEntry) {
190
147
  return undefined;
191
148
  }
192
- return {
193
- ...result,
194
- resolvedPath: entry,
195
- resolveFrom: undefined,
196
- bindExports: false,
197
- };
149
+ return (this.instances.locate(instance, realFolder(canonicalEntry)) ??
150
+ canonicalEntry);
198
151
  }
199
152
  getInterfaceGraphRoot(filePath) {
200
- const packageName = this.interfaceGraphFiles.get(filePath);
201
- if (!packageName) {
202
- return undefined;
203
- }
204
- if (packageName === CORE_PKG) {
205
- return CORE_PACKAGE?.root;
206
- }
207
- return this.interfacePackages.get(packageName);
153
+ const instance = this.instanceFiles.get(filePath) ??
154
+ this.owners.findOwner(filePath)?.instance;
155
+ return instance ? this.instances.rootOf(instance) : undefined;
208
156
  }
209
- buildProviderRoutes(moduleId) {
210
- const routes = {};
211
- this.bindKnownRoutes(moduleId, routes);
212
- return routes;
157
+ releaseInstances() {
158
+ this.instances.release();
213
159
  }
214
160
  clearCache() {
215
- for (const event of this.routedEvents.values()) {
216
- internal_1.internal.knownEvents.delete(event);
217
- const identity = (0, interface_core_1.GetInterfaceProxyIdentity)(event);
218
- if (identity) {
219
- internal_1.internal.proxyStates.delete(identity);
220
- }
221
- }
222
- this.routedEvents.clear();
223
- this.interfaceGraphFiles.clear();
224
- this.interfaceDependencies.clear();
225
- this.proxyOwners.clear();
226
- this.localModuleOwners.invalidate();
227
- this.interfacePackageOwners.invalidate();
228
- }
229
- registerProxyOwners(interfaceName, references) {
230
- for (const { identity, proxy } of references) {
231
- const owner = this.proxyOwners.get(identity);
232
- if (!owner) {
233
- this.proxyOwners.set(identity, {
234
- interfaceName,
235
- proxies: new WeakSet([proxy]),
236
- });
237
- continue;
238
- }
239
- if (owner.interfaceName !== interfaceName && !owner.proxies.has(proxy)) {
240
- throw new Error(`Interface packages '${owner.interfaceName}' and '${interfaceName}' declare distinct proxies with identity '${identity}'. Use unique interface proxy identities.`);
241
- }
242
- owner.proxies.add(proxy);
243
- }
161
+ this.instanceFiles.clear();
162
+ this.owners.invalidate();
244
163
  }
245
- bindImportedRoutes(context, result, references) {
246
- for (const { identity } of references) {
247
- const owner = this.proxyOwners.get(identity)?.interfaceName;
248
- if (result.interfaceName && owner !== result.interfaceName) {
249
- continue;
164
+ retireInstance(instance) {
165
+ for (const [file, owner] of this.instanceFiles) {
166
+ if (owner === instance) {
167
+ this.instanceFiles.delete(file);
250
168
  }
251
- this.bindRoute(context.module, context.providerRoutes, identity, result.provider);
252
169
  }
170
+ (0, modules_1.ReleaseOwner)(`${instance}${INSTANCE_OWNER_SUFFIX}`);
253
171
  }
254
- replayKnownRoutes(context) {
255
- this.bindKnownRoutes(context.module, context.providerRoutes);
256
- }
257
- bindKnownRoutes(moduleId, routes) {
258
- const module = this.modulesById.get(moduleId);
259
- if (!module) {
260
- return;
261
- }
262
- for (const [identity, { interfaceName }] of this.proxyOwners) {
263
- for (const provider of this.resolveProviders(module, interfaceName)) {
264
- this.bindRoute(moduleId, routes, identity, provider);
172
+ canonicalPackages() {
173
+ const canonical = new Map();
174
+ for (const [name, root] of this.interfacePackages) {
175
+ if (name !== CORE_PKG) {
176
+ canonical.set(name, {
177
+ root: node_path_1.default.resolve(root),
178
+ realRoot: realFolder(root),
179
+ });
265
180
  }
266
181
  }
182
+ return canonical;
267
183
  }
268
- bindRoute(moduleId, routes, identity, provider) {
269
- const current = routes[identity];
270
- if (current && current !== provider) {
271
- throw new Error(`Module '${moduleId}' resolves proxy '${identity}' to both '${current}' and '${provider}'. Use unique interface proxy identities.`);
184
+ fixedRoots() {
185
+ const roots = new Map();
186
+ for (const name of this.lifecycleInterfacePackages) {
187
+ for (const key of this.instances.keysOf(name)) {
188
+ const provider = this.instances.describe(key)?.provider;
189
+ const module = provider ? this.modulesById.get(provider) : undefined;
190
+ if (module?.manifest.manifest.name === name) {
191
+ roots.set(key, realFolder(module.manifest.folder));
192
+ }
193
+ }
272
194
  }
273
- routes[identity] = provider;
195
+ return roots;
274
196
  }
275
197
  resolveInterfaceCore(request) {
276
198
  if (request === CORE_PKG) {
@@ -281,485 +203,105 @@ class Resolver {
281
203
  }
282
204
  return undefined;
283
205
  }
284
- resolveInterfacePackage(request) {
285
- for (const [packageName, rootDir] of this.interfacePackages) {
286
- if (request === packageName) {
287
- return {
288
- packageName,
289
- result: {
290
- resolvedPath: this.interfacePackageEntries.get(packageName) ?? rootDir,
291
- },
292
- };
293
- }
294
- if (request.startsWith(`${packageName}/`)) {
295
- return {
296
- packageName,
297
- result: {
298
- resolvedPath: request,
299
- resolveFrom: this.interfacePackageResolveFrom.get(packageName) ?? rootDir,
300
- },
301
- };
302
- }
303
- }
304
- return undefined;
305
- }
306
- resolveRelativeInterface(request, parent, parentModule) {
307
- if (!request.startsWith(".") || !parent?.filename) {
308
- return undefined;
309
- }
310
- const packageName = this.findInterfacePackageByPath(parent.filename);
206
+ resolveInterfaceRequest(request, owner) {
207
+ const connection = parseConnection(request);
208
+ const target = connection?.request ?? request;
209
+ const packageName = this.findInterfacePackage(target);
311
210
  if (!packageName) {
211
+ if (connection) {
212
+ throw new Error(`Connection path '${request}' does not name an interface package.`);
213
+ }
312
214
  return undefined;
313
215
  }
314
- return this.bindResultProvider({ resolvedPath: request }, packageName, {
315
- bindExports: !this.interfaceGraphFiles.has(parent.filename),
316
- sharedExports: true,
317
- }, parent, parentModule);
216
+ const instance = connection
217
+ ? this.connectionInstance(owner, packageName, connection.index)
218
+ : this.instanceFor(owner, packageName);
219
+ return { ...this.canonicalRequest(packageName, target), instance };
318
220
  }
319
- bindResultProvider(result, packageName, binding, parent, parentModule) {
320
- const provider = this.resolveRequestProvider(packageName, parent?.filename, parentModule);
221
+ canonicalRequest(packageName, request) {
222
+ const root = this.interfacePackages.get(packageName);
223
+ if (request === packageName) {
224
+ return {
225
+ resolvedPath: this.interfacePackageEntries.get(packageName) ?? root,
226
+ };
227
+ }
321
228
  return {
322
- ...result,
323
- bindExports: binding.bindExports,
324
- sharedExports: binding.sharedExports,
325
- interfaceName: packageName,
326
- provider,
229
+ resolvedPath: request,
230
+ resolveFrom: this.interfacePackageResolveFrom.get(packageName) ?? root,
327
231
  };
328
232
  }
329
- isInterfacePackageFile(filename) {
330
- if (!filename) {
331
- return false;
332
- }
333
- return (this.interfaceGraphFiles.has(filename) ||
334
- this.findInterfacePackageByPath(filename) !== undefined);
335
- }
336
- resolveProvider(module, packageName) {
337
- if (module.manifest.implements?.includes(packageName)) {
338
- return module.id;
339
- }
340
- return internal_1.internal.interfaceConnections[module.id]?.[packageName]?.find(({ selected }) => selected)?.provider;
233
+ findInterfacePackage(request) {
234
+ return [...this.interfacePackages.keys()].find((packageName) => packageName !== CORE_PKG &&
235
+ (request === packageName || request.startsWith(`${packageName}/`)));
341
236
  }
342
- resolveRequestProvider(packageName, parentFilename, parentModule) {
237
+ contextOwner() {
343
238
  const contextModule = (0, internal_1.getModuleContext)()?.module;
344
- const consumer = contextModule
239
+ const module = contextModule
345
240
  ? this.modulesById.get(contextModule)
346
241
  : undefined;
347
- const direct = consumer
348
- ? this.resolveProvider(consumer, packageName)
349
- : undefined;
350
- if (direct) {
351
- return direct;
352
- }
353
- const parentInterface = parentFilename
354
- ? this.interfaceGraphFiles.get(parentFilename)
355
- : undefined;
356
- const inherited = consumer && parentInterface
357
- ? this.resolveChildProvider(consumer, parentInterface, packageName)
358
- : undefined;
359
- return (inherited ??
360
- (parentModule
361
- ? this.resolveProvider(parentModule, packageName)
362
- : undefined));
363
- }
364
- resolveChildProvider(consumer, parentInterface, childInterface) {
365
- for (const provider of this.resolveProviders(consumer, parentInterface)) {
366
- const providerModule = this.modulesById.get(provider);
367
- const childProvider = providerModule
368
- ? this.resolveProvider(providerModule, childInterface)
369
- : undefined;
370
- if (childProvider) {
371
- return childProvider;
372
- }
373
- }
374
- return undefined;
375
- }
376
- resolveProviders(module, interfaceName, visited = new Set()) {
377
- const direct = this.resolveProvider(module, interfaceName);
378
- if (direct) {
379
- return new Set([direct]);
380
- }
381
- if (visited.has(interfaceName)) {
382
- return new Set();
383
- }
384
- visited.add(interfaceName);
385
- const providers = new Set();
386
- for (const [parent, children] of this.interfaceDependencies) {
387
- if (!children.has(interfaceName)) {
388
- continue;
389
- }
390
- this.collectChildProviders(module, parent, interfaceName, visited, providers);
391
- }
392
- return providers;
393
- }
394
- collectChildProviders(module, parentInterface, childInterface, visited, providers) {
395
- for (const parentProvider of this.resolveProviders(module, parentInterface, new Set(visited))) {
396
- const providerModule = this.modulesById.get(parentProvider);
397
- const childProvider = providerModule
398
- ? this.resolveProvider(providerModule, childInterface)
399
- : undefined;
400
- if (childProvider) {
401
- providers.add(childProvider);
402
- }
403
- }
404
- }
405
- trackInterfaceDependency(parentFilename, childInterface) {
406
- const parentInterface = parentFilename
407
- ? this.interfaceGraphFiles.get(parentFilename)
408
- : undefined;
409
- if (!parentInterface || parentInterface === childInterface) {
410
- return;
411
- }
412
- const dependencies = this.interfaceDependencies.get(parentInterface) ?? new Set();
413
- dependencies.add(childInterface);
414
- this.interfaceDependencies.set(parentInterface, dependencies);
242
+ return module ? { module } : undefined;
415
243
  }
416
- findRequestedInterface(request, parentFilename) {
417
- if (request === CORE_PKG || request.startsWith(`${CORE_PKG}/`)) {
418
- return CORE_PKG;
419
- }
420
- const direct = this.findInterfacePackageRequest(request);
421
- if (direct) {
422
- return direct;
244
+ scopeOf(owner) {
245
+ if (owner?.module) {
246
+ return this.bindings?.modules.get(owner.module.id)?.keys ?? new Map();
423
247
  }
424
- return request.startsWith(".") && parentFilename
425
- ? this.findInterfacePackageByPath(parentFilename)
426
- : undefined;
427
- }
428
- findInterfacePackageRequest(request) {
429
- return [...this.interfacePackages.keys()].find((packageName) => request === packageName || request.startsWith(`${packageName}/`));
430
- }
431
- findInterfacePackageByPath(fileName) {
432
- return this.interfacePackageOwners.findOwner(fileName);
248
+ return owner?.instance ? this.instanceScope(owner.instance) : new Map();
433
249
  }
434
- listInterfacePackageRoots() {
435
- const coreRoots = CORE_PACKAGE
436
- ? [{ root: CORE_PACKAGE.root, owner: CORE_PKG }]
437
- : [];
438
- const packageRoots = [...this.interfacePackages].map(([packageName, root]) => ({ root, owner: packageName }));
439
- return [...coreRoots, ...packageRoots];
440
- }
441
- bindInterfaceValue(value, context) {
442
- if (isRecognizedInterfaceProxy(value, "event")) {
443
- return this.getRoutedEvent(value, context);
444
- }
445
- if (typeof value === "function" &&
446
- this.isClass(value)) {
447
- return value;
448
- }
449
- if (!this.isBindableValue(value)) {
450
- return value;
451
- }
452
- const cached = this.boundValues.get(value)?.get(context);
453
- if (cached) {
454
- return cached;
455
- }
456
- const bound = typeof value === "function"
457
- ? this.createFunctionFacade(value, context)
458
- : this.createObjectFacade(value, context);
459
- const contexts = this.boundValues.get(value) ??
460
- new WeakMap();
461
- contexts.set(context, bound);
462
- this.boundValues.set(value, contexts);
463
- return bound;
464
- }
465
- bindPassedValue(value, context) {
466
- return this.needsFacade(value)
467
- ? this.bindInterfaceValue(value, context)
468
- : value;
469
- }
470
- needsFacade(value, visited) {
471
- if (typeof value === "function") {
472
- return true;
473
- }
474
- if (typeof value !== "object" ||
475
- value === null ||
476
- node_util_1.types.isProxy(value)) {
477
- return false;
250
+ instanceScope(instance) {
251
+ const descriptor = this.instances.describe(instance);
252
+ if (descriptor?.provider) {
253
+ return this.bindings?.modules.get(descriptor.provider)?.keys ?? new Map();
478
254
  }
479
- if (!isPlainContainer(value)) {
480
- return isRecognizedInterfaceProxy(value);
481
- }
482
- return (isBrandedInterfaceProxy(value) || this.holdsFacadeMember(value, visited));
483
- }
484
- holdsFacadeMember(container, visited = new Set()) {
485
- if (visited.has(container)) {
486
- return false;
487
- }
488
- visited.add(container);
489
- for (const member of Object.values(container)) {
490
- if (this.needsFacade(member, visited)) {
491
- return true;
255
+ const scope = new Map();
256
+ for (const key of descriptor?.dependencies ?? []) {
257
+ const dependency = this.bindings?.instances.get(key);
258
+ if (dependency) {
259
+ scope.set(dependency.interfaceName, key);
492
260
  }
493
261
  }
494
- return false;
262
+ return scope;
495
263
  }
496
- bindStubbedInterfaceValue(result, value, context) {
497
- if (!result.interfaceName ||
498
- !this.stubbedInterfacePackages.has(result.interfaceName)) {
499
- return value;
264
+ describeOwner(owner) {
265
+ if (owner?.module) {
266
+ return `Module '${owner.module.id}'`;
500
267
  }
501
- const providerless = this.getProviderlessContext(this.getBindingContext(result, context), result.interfaceName);
502
- return this.bindInterfaceValue(value, providerless);
268
+ return owner?.instance
269
+ ? `Interface instance '${owner.instance}'`
270
+ : "Code outside any module";
503
271
  }
504
- getBindingContext(result, context) {
505
- if (!result.sharedExports) {
506
- return this.interfaceBodySharedContexts.get(context) ?? context;
507
- }
508
- return this.getSharedInterfaceContext(result, context);
509
- }
510
- getSharedInterfaceContext(result, context) {
511
- const importer = this.interfaceBodySharedContexts.get(context) ?? context;
512
- const interfaceName = result.interfaceName ?? "";
513
- const contexts = this.sharedInterfaceContexts.get(importer) ?? new Map();
514
- const existing = contexts.get(interfaceName);
515
- if (existing) {
516
- return existing;
272
+ instanceFor(owner, packageName) {
273
+ const bound = this.scopeOf(owner).get(packageName);
274
+ if (bound) {
275
+ return bound;
517
276
  }
518
- const shared = { ...importer, provider: result.provider };
519
- contexts.set(interfaceName, shared);
520
- this.sharedInterfaceContexts.set(importer, contexts);
521
- this.sharedContexts.set(shared, interfaceName);
522
- return shared;
523
- }
524
- getInterfaceBodyContext(result, context) {
525
- const shared = this.getSharedInterfaceContext(result, context);
526
- const existing = this.interfaceBodyContexts.get(shared);
527
- if (existing) {
528
- return existing;
277
+ const keys = this.instances.keysOf(packageName);
278
+ if (keys.length <= 1) {
279
+ return keys[0];
529
280
  }
530
- const body = this.createInterfaceBodyContext(shared, result.interfaceName ?? "");
531
- this.interfaceBodyContexts.set(shared, body);
532
- this.interfaceBodySharedContexts.set(body, shared);
533
- return body;
534
- }
535
- createInterfaceBodyContext(shared, interfaceName) {
536
- const packageContext = {
537
- module: shared.module,
538
- owner: `${interfaceName}${SHARED_INTERFACE_OWNER_SUFFIX}`,
539
- provider: shared.provider,
540
- providerRoutes: shared.providerRoutes,
541
- };
542
- return (0, internal_1.runWithModuleContext)(packageContext, () => (0, internal_1.captureModuleContext)());
281
+ throw new Error(`${this.describeOwner(owner)} imports ${packageName}, which has several instances (${keys.join(", ")}), but does not declare it; add it to the dependencies of the importing package.`);
543
282
  }
544
- effectiveContext(context) {
545
- const sharedInterface = this.sharedContexts.get(context);
546
- if (sharedInterface === undefined) {
547
- return context;
548
- }
549
- const ambient = (0, internal_1.captureModuleContext)();
550
- if (!ambient) {
551
- return context;
552
- }
553
- const adopted = this.getAdoptedContext(context, ambient, sharedInterface);
554
- const stubbed = this.sharedStubInterfaces.get(context);
555
- return stubbed ? this.getProviderlessContext(adopted, stubbed) : adopted;
556
- }
557
- getAdoptedContext(shared, ambient, interfaceName) {
558
- const cached = this.adoptedContexts.get(shared)?.get(ambient);
559
- if (cached) {
560
- return cached;
561
- }
562
- const adopted = {
563
- ...ambient,
564
- provider: this.adoptedProvider(interfaceName, ambient, shared),
565
- providerRoutes: this.chainProviderRoutes(ambient.providerRoutes, shared.providerRoutes),
566
- };
567
- const contexts = this.adoptedContexts.get(shared) ??
568
- new WeakMap();
569
- contexts.set(ambient, adopted);
570
- this.adoptedContexts.set(shared, contexts);
571
- return adopted;
572
- }
573
- adoptedProvider(interfaceName, ambient, shared) {
574
- const consumer = this.modulesById.get(ambient.module);
575
- const direct = consumer
576
- ? this.resolveProvider(consumer, interfaceName)
577
- : undefined;
578
- return direct ?? shared.provider;
579
- }
580
- chainProviderRoutes(routes, fallback) {
581
- if (!routes || !fallback) {
582
- return routes ?? fallback;
583
- }
584
- return new Proxy(routes, {
585
- get: (target, identity) => Reflect.get(target, identity) ?? Reflect.get(fallback, identity),
586
- });
587
- }
588
- getProviderlessContext(context, interfaceName) {
589
- const contexts = this.providerlessContexts.get(context) ?? new Map();
590
- const existing = contexts.get(interfaceName);
591
- if (existing) {
592
- return existing;
593
- }
594
- const providerless = {
595
- ...context,
596
- provider: undefined,
597
- providerRoutes: this.filterStubbedProviderRoutes(context, interfaceName),
598
- };
599
- contexts.set(interfaceName, providerless);
600
- this.providerlessContexts.set(context, contexts);
601
- this.stubbedContexts.add(providerless);
602
- const sharedInterface = this.sharedContexts.get(context);
603
- if (sharedInterface !== undefined) {
604
- this.sharedContexts.set(providerless, sharedInterface);
605
- this.sharedStubInterfaces.set(providerless, interfaceName);
606
- }
607
- return providerless;
608
- }
609
- filterStubbedProviderRoutes(context, interfaceName) {
610
- const routes = context.providerRoutes ?? {};
611
- return new Proxy(routes, {
612
- get: (target, identity) => {
613
- const owner = typeof identity === "string"
614
- ? this.proxyOwners.get(identity)?.interfaceName
615
- : undefined;
616
- if (owner === interfaceName &&
617
- this.stubbedInterfacePackages.has(interfaceName)) {
618
- return undefined;
619
- }
620
- return Reflect.get(target, identity);
621
- },
622
- });
623
- }
624
- isBindableValue(value) {
625
- if ((typeof value !== "object" && typeof value !== "function") ||
626
- value === null) {
627
- return false;
628
- }
629
- if (node_util_1.types.isProxy(value)) {
630
- return false;
631
- }
632
- if (typeof value === "function" || isRecognizedInterfaceProxy(value)) {
633
- return true;
634
- }
635
- return isPlainContainer(value);
636
- }
637
- isClass(value) {
638
- return Function.prototype.toString.call(value).startsWith(CLASS_PREFIX);
639
- }
640
- createObjectFacade(value, context) {
641
- const members = new Map();
642
- const facade = new Proxy(value, {
643
- get: (target, property) => {
644
- const descriptor = Reflect.getOwnPropertyDescriptor(target, property);
645
- if (descriptor &&
646
- !descriptor.configurable &&
647
- "value" in descriptor &&
648
- !descriptor.writable) {
649
- return descriptor.value;
650
- }
651
- const member = Reflect.get(target, property, target);
652
- const cached = members.get(property);
653
- if (cached && Object.is(cached.source, member)) {
654
- return cached.bound;
655
- }
656
- const bound = typeof member === "function" && !this.isClass(member)
657
- ? this.bindObjectFunction(member, target, facade, property, context)
658
- : this.bindPassedValue(member, context);
659
- members.set(property, { bound, source: member });
660
- return bound;
661
- },
662
- });
663
- return facade;
664
- }
665
- bindObjectFunction(member, target, facade, property, context) {
666
- const isStubAttachment = this.stubbedContexts.has(context) &&
667
- isRecognizedInterfaceProxy(target) &&
668
- PROXY_ATTACHMENT_METHODS.has(property);
669
- return isStubAttachment
670
- ? member.bind(target)
671
- : this.createFunctionFacade(member, context, target, facade);
672
- }
673
- createFunctionFacade(value, context, boundThis, facadeThis) {
674
- return new Proxy(value, {
675
- apply: (target, thisArg, argumentsList) => {
676
- const receiver = boundThis &&
677
- (!facadeThis || thisArg === facadeThis || thisArg === undefined)
678
- ? boundThis
679
- : thisArg;
680
- const result = (0, internal_1.runWithCapturedModuleContext)(this.effectiveContext(context), () => Reflect.apply(target, receiver, argumentsList.map((argument) => this.bindPassedValue(argument, context))));
681
- return this.bindFunctionResult(result, context);
682
- },
683
- construct: (target, argumentsList, newTarget) => (0, internal_1.runWithCapturedModuleContext)(this.effectiveContext(context), () => Reflect.construct(target, argumentsList, newTarget)),
684
- get: (target, property) => {
685
- if (property === "prototype") {
686
- return target.prototype;
687
- }
688
- return this.bindInterfaceValue(Reflect.get(target, property, target), context);
689
- },
690
- });
691
- }
692
- bindFunctionResult(value, context) {
693
- if (value instanceof Promise) {
694
- return value.then((result) => typeof result === "function"
695
- ? this.bindInterfaceValue(result, context)
696
- : result);
697
- }
698
- return typeof value === "function"
699
- ? this.bindInterfaceValue(value, context)
700
- : value;
701
- }
702
- getRoutedEvent(value, context) {
703
- const identity = (0, interface_core_1.GetInterfaceProxyIdentity)(value);
704
- const provider = identity
705
- ? (context.providerRoutes?.[identity] ?? context.provider)
283
+ connectionInstance(owner, packageName, index) {
284
+ const module = owner?.module;
285
+ const key = module
286
+ ? this.bindings?.modules
287
+ .get(module.id)
288
+ ?.connectionKeys.get(packageName)?.[index]
706
289
  : undefined;
707
- if (!identity || !provider) {
708
- return value;
709
- }
710
- const key = `${identity}\0${provider}`;
711
- const routed = this.routedEvents.get(key);
712
- if (routed) {
713
- return this.bindRoutedEvent(routed, context);
714
- }
715
- const created = new interface_core_1.EventProxy(`${this.resolverIdentity}:${provider}:${identity}`);
716
- this.routedEvents.set(key, created);
717
- return this.bindRoutedEvent(created, context);
718
- }
719
- bindRoutedEvent(event, context) {
720
- const cached = this.boundValues.get(event)?.get(context);
721
- if (cached) {
722
- return cached;
723
- }
724
- const bound = this.createEventFacade(event, context);
725
- const contexts = this.boundValues.get(event) ??
726
- new WeakMap();
727
- contexts.set(context, bound);
728
- this.boundValues.set(event, contexts);
729
- return bound;
730
- }
731
- createEventFacade(event, context) {
732
- const handlers = new WeakMap();
733
- const register = (handler) => {
734
- const bound = handlers.get(handler) ?? this.createFunctionFacade(handler, context);
735
- handlers.set(handler, bound);
736
- return (0, internal_1.runWithCapturedModuleContext)(this.effectiveContext(context), () => event.register(bound));
737
- };
738
- const unregister = (handler) => (0, internal_1.runWithCapturedModuleContext)(this.effectiveContext(context), () => event.unregister(handlers.get(handler) ?? handler));
739
- const emit = this.createFunctionFacade(event.emit, context, event);
740
- return new Proxy(event, {
741
- get: (target, property) => {
742
- if (property === "register") {
743
- return register;
744
- }
745
- if (property === "unregister") {
746
- return unregister;
747
- }
748
- if (property === "emit") {
749
- return emit;
750
- }
751
- return Reflect.get(target, property, target);
752
- },
753
- });
754
- }
755
- resolveLocalModule(fileName) {
756
- if (!fileName) {
757
- return undefined;
758
- }
759
- return this.localModuleOwners.findOwner(fileName);
760
- }
761
- listModuleRoots() {
762
- return [...this.moduleByFolder].map(([root, owner]) => ({ root, owner }));
290
+ if (!key) {
291
+ throw new Error(`${this.describeOwner(owner)} has no connection ${index} to ${packageName}.`);
292
+ }
293
+ return key;
294
+ }
295
+ listOwnerRoots() {
296
+ const modules = [...this.moduleByFolder].map(([root, module]) => ({
297
+ root,
298
+ owner: { module },
299
+ }));
300
+ const instances = [...this.instances.roots()].map(([instance, root]) => ({
301
+ root,
302
+ owner: { instance },
303
+ }));
304
+ return [...modules, ...instances];
763
305
  }
764
306
  }
765
307
  exports.Resolver = Resolver;