mount-observer 0.1.12 → 0.1.13
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/DefineCustomElementHandler.js +99 -99
- package/ElementMountExtension.js +183 -8
- package/ElementMountExtension.ts +218 -11
- package/EnhanceMountedElementHandler.js +96 -96
- package/Events.js +18 -18
- package/Events.ts +6 -6
- package/EvtRt.js +16 -14
- package/EvtRt.ts +18 -15
- package/MountObserver.js +186 -71
- package/MountObserver.ts +207 -85
- package/README.md +1345 -151
- package/RegistryMountCoordinator.js +125 -0
- package/RegistryMountCoordinator.ts +181 -0
- package/connectionMonitor.js +1 -1
- package/connectionMonitor.ts +1 -1
- package/{getRootRegistryContainer.js → getRegistryRoot.js} +1 -1
- package/{getRootRegistryContainer.ts → getRegistryRoot.ts} +1 -1
- package/index.js +15 -10
- package/index.ts +15 -10
- package/mediaQuery.js +1 -1
- package/mediaQuery.ts +1 -1
- package/observedRootHas.js +87 -87
- package/package.json +67 -61
- package/playwright.config.ts +1 -0
- package/rootSizeObserver.js +1 -1
- package/rootSizeObserver.ts +1 -1
- package/upShadowSearch.js +64 -0
- package/upShadowSearch.ts +62 -0
- package/DefineCustomElementHandler.ts +0 -117
- package/EnhanceMountedElementHandler.ts +0 -111
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coordinates MountObserver instances across multiple DOM scopes that share
|
|
3
|
+
* the same CustomElementRegistry. This enables "mutually assured observing"
|
|
4
|
+
* where all scopes with the same registry share mount observers.
|
|
5
|
+
*/
|
|
6
|
+
const regObsGuid = 'iqj6MOueu0OP4CQi1a_4Sw';
|
|
7
|
+
/**
|
|
8
|
+
* Maps CustomElementRegistry -> Map<MountConfig, WeakMap<Node, ObserverEntry>>
|
|
9
|
+
* The MountConfig object itself is used as the key (object identity).
|
|
10
|
+
* The innermost WeakMap maps registry root nodes to their observer entries.
|
|
11
|
+
*/
|
|
12
|
+
export function getRegistryObservers() {
|
|
13
|
+
if (!globalThis[regObsGuid]) {
|
|
14
|
+
globalThis[regObsGuid] = new WeakMap();
|
|
15
|
+
}
|
|
16
|
+
return globalThis[regObsGuid];
|
|
17
|
+
}
|
|
18
|
+
const registryScopeId = 'pt9dS-V7U0SC3Yk708_5Ww';
|
|
19
|
+
/**
|
|
20
|
+
* Tracks all registry root nodes for each CustomElementRegistry.
|
|
21
|
+
* Used to iterate over all scopes when a new config is added.
|
|
22
|
+
*/
|
|
23
|
+
export function getRegistryScopes() {
|
|
24
|
+
if (!globalThis[registryScopeId]) {
|
|
25
|
+
globalThis[registryScopeId] = new WeakMap();
|
|
26
|
+
}
|
|
27
|
+
return globalThis[registryScopeId];
|
|
28
|
+
}
|
|
29
|
+
// const registryScopes = new WeakMap<
|
|
30
|
+
// CustomElementRegistry,
|
|
31
|
+
// WeakDual<Node>
|
|
32
|
+
// >();
|
|
33
|
+
// Note: assignGingerly.ts already has a polyfill for getOrInsertComputed.
|
|
34
|
+
// If this code will already have imported assignGingerly, then no need for the duplicate polyfill below.
|
|
35
|
+
// Polyfill for Map.prototype.getOrInsertComputed and WeakMap.prototype.getOrInsertComputed
|
|
36
|
+
if (typeof Map.prototype.getOrInsertComputed !== 'function') {
|
|
37
|
+
Map.prototype.getOrInsertComputed = function (key, insert) {
|
|
38
|
+
if (this.has(key))
|
|
39
|
+
return this.get(key);
|
|
40
|
+
const value = insert();
|
|
41
|
+
this.set(key, value);
|
|
42
|
+
return value;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
if (typeof WeakMap.prototype.getOrInsertComputed !== 'function') {
|
|
46
|
+
WeakMap.prototype.getOrInsertComputed = function (key, insert) {
|
|
47
|
+
if (this.has(key))
|
|
48
|
+
return this.get(key);
|
|
49
|
+
const value = insert();
|
|
50
|
+
this.set(key, value);
|
|
51
|
+
return value;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Helper to create an observer entry asynchronously.
|
|
56
|
+
* Separated to handle async operations cleanly.
|
|
57
|
+
*/
|
|
58
|
+
async function createObserverEntry(config, registryRoot) {
|
|
59
|
+
// Dynamically import to avoid circular dependency
|
|
60
|
+
const { MountObserver: MountObserverClass } = await import('./MountObserver.js');
|
|
61
|
+
const observer = new MountObserverClass(config);
|
|
62
|
+
await observer.observe(registryRoot);
|
|
63
|
+
return {
|
|
64
|
+
config,
|
|
65
|
+
registryRootRef: new WeakRef(registryRoot),
|
|
66
|
+
observer
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Get or create a mount observer for a specific registry + config + registry root combination.
|
|
71
|
+
* This function ensures that:
|
|
72
|
+
* 1. The config is registered with the registry's mountConfigRegistry
|
|
73
|
+
* 2. An observer exists for this specific registry root
|
|
74
|
+
* 3. All other registry roots with the same registry get observers for this config
|
|
75
|
+
* 4. All other configs get observers for this registry root
|
|
76
|
+
*
|
|
77
|
+
* @returns The ObserverEntry for the requested combination
|
|
78
|
+
*/
|
|
79
|
+
export async function getOrInsertObserverEntry(registry, config, registryRoot) {
|
|
80
|
+
// Add config to the registry's config list (if not already there)
|
|
81
|
+
registry.mountConfigRegistry.push(config);
|
|
82
|
+
// Get or create the nested map structure
|
|
83
|
+
const mountConfigMap = (getRegistryObservers()).getOrInsertComputed(registry, () => new Map());
|
|
84
|
+
const nodeToObserverMap = mountConfigMap.getOrInsertComputed(config, () => new WeakMap());
|
|
85
|
+
// Get or create the observer for this specific registry root
|
|
86
|
+
let observerEntry = nodeToObserverMap.get(registryRoot);
|
|
87
|
+
if (!observerEntry) {
|
|
88
|
+
observerEntry = await createObserverEntry(config, registryRoot);
|
|
89
|
+
nodeToObserverMap.set(registryRoot, observerEntry);
|
|
90
|
+
}
|
|
91
|
+
// Track this registry root in the scopes set
|
|
92
|
+
const scopes = getRegistryScopes().getOrInsertComputed(registry, () => ({
|
|
93
|
+
weakSet: new WeakSet(),
|
|
94
|
+
setWeak: new Set()
|
|
95
|
+
}));
|
|
96
|
+
// Add to tracking sets if not already present
|
|
97
|
+
if (!scopes.weakSet.has(registryRoot)) {
|
|
98
|
+
scopes.weakSet.add(registryRoot);
|
|
99
|
+
scopes.setWeak.add(new WeakRef(registryRoot));
|
|
100
|
+
}
|
|
101
|
+
// Get all configs for this registry
|
|
102
|
+
const configs = registry.mountConfigRegistry.items;
|
|
103
|
+
// Iterate over all known registry roots for this registry
|
|
104
|
+
const arr = Array.from(scopes.setWeak);
|
|
105
|
+
for (const regRootRef of arr) {
|
|
106
|
+
const regRoot = regRootRef.deref();
|
|
107
|
+
if (regRoot === undefined)
|
|
108
|
+
continue;
|
|
109
|
+
// For each config, ensure an observer exists for this registry root
|
|
110
|
+
for (const conf of configs) {
|
|
111
|
+
// Skip if this is the same config + root we just created
|
|
112
|
+
if (conf === config && registryRoot === regRoot)
|
|
113
|
+
continue;
|
|
114
|
+
// Get or create observer for this conf + regRoot combination
|
|
115
|
+
// This won't cause infinite loop because we only create if missing
|
|
116
|
+
const confObserverMap = mountConfigMap.getOrInsertComputed(conf, () => new WeakMap());
|
|
117
|
+
let existingEntry = confObserverMap.get(regRoot);
|
|
118
|
+
if (!existingEntry) {
|
|
119
|
+
existingEntry = await createObserverEntry(conf, regRoot);
|
|
120
|
+
confObserverMap.set(regRoot, existingEntry);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return observerEntry;
|
|
125
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coordinates MountObserver instances across multiple DOM scopes that share
|
|
3
|
+
* the same CustomElementRegistry. This enables "mutually assured observing"
|
|
4
|
+
* where all scopes with the same registry share mount observers.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { MountConfig, WeakDual } from './types/mount-observer/types.js';
|
|
8
|
+
import type { MountObserver } from './MountObserver.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Represents a single MountObserver observing a specific registry root.
|
|
12
|
+
*/
|
|
13
|
+
type ObserverEntry = {
|
|
14
|
+
config: MountConfig; // Store for reference
|
|
15
|
+
registryRootRef: WeakRef<Node>;
|
|
16
|
+
observer: MountObserver;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const regObsGuid = 'iqj6MOueu0OP4CQi1a_4Sw';
|
|
20
|
+
|
|
21
|
+
export type CER2MC2N2OE = WeakMap<
|
|
22
|
+
CustomElementRegistry,
|
|
23
|
+
Map<
|
|
24
|
+
MountConfig,
|
|
25
|
+
WeakMap<Node, ObserverEntry>
|
|
26
|
+
>
|
|
27
|
+
>
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Maps CustomElementRegistry -> Map<MountConfig, WeakMap<Node, ObserverEntry>>
|
|
31
|
+
* The MountConfig object itself is used as the key (object identity).
|
|
32
|
+
* The innermost WeakMap maps registry root nodes to their observer entries.
|
|
33
|
+
*/
|
|
34
|
+
export function getRegistryObservers(): CER2MC2N2OE{
|
|
35
|
+
if (!(globalThis as any)[regObsGuid]) {
|
|
36
|
+
(globalThis as any)[regObsGuid] = new WeakMap<CustomElementRegistry,
|
|
37
|
+
Map<
|
|
38
|
+
MountConfig,
|
|
39
|
+
WeakMap<Node, ObserverEntry>
|
|
40
|
+
>
|
|
41
|
+
>();
|
|
42
|
+
}
|
|
43
|
+
return (globalThis as any)[regObsGuid] as CER2MC2N2OE;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
const registryScopeId = 'pt9dS-V7U0SC3Yk708_5Ww';
|
|
48
|
+
|
|
49
|
+
export type CER2WD = WeakMap<
|
|
50
|
+
CustomElementRegistry,
|
|
51
|
+
WeakDual<Node>
|
|
52
|
+
>
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Tracks all registry root nodes for each CustomElementRegistry.
|
|
56
|
+
* Used to iterate over all scopes when a new config is added.
|
|
57
|
+
*/
|
|
58
|
+
export function getRegistryScopes(): CER2WD{
|
|
59
|
+
if (!(globalThis as any)[registryScopeId]) {
|
|
60
|
+
(globalThis as any)[registryScopeId] = new WeakMap<
|
|
61
|
+
CustomElementRegistry,
|
|
62
|
+
WeakDual<Node>
|
|
63
|
+
>();
|
|
64
|
+
}
|
|
65
|
+
return (globalThis as any)[registryScopeId] as CER2WD;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
// const registryScopes = new WeakMap<
|
|
70
|
+
// CustomElementRegistry,
|
|
71
|
+
// WeakDual<Node>
|
|
72
|
+
// >();
|
|
73
|
+
|
|
74
|
+
// Note: assignGingerly.ts already has a polyfill for getOrInsertComputed.
|
|
75
|
+
// If this code will already have imported assignGingerly, then no need for the duplicate polyfill below.
|
|
76
|
+
|
|
77
|
+
// Polyfill for Map.prototype.getOrInsertComputed and WeakMap.prototype.getOrInsertComputed
|
|
78
|
+
if (typeof Map.prototype.getOrInsertComputed !== 'function') {
|
|
79
|
+
(Map.prototype as any).getOrInsertComputed = function(key: any, insert: () => any) {
|
|
80
|
+
if (this.has(key)) return this.get(key);
|
|
81
|
+
const value = insert();
|
|
82
|
+
this.set(key, value);
|
|
83
|
+
return value;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
if (typeof WeakMap.prototype.getOrInsertComputed !== 'function') {
|
|
87
|
+
(WeakMap.prototype as any).getOrInsertComputed = function(key: any, insert: () => any) {
|
|
88
|
+
if (this.has(key)) return this.get(key);
|
|
89
|
+
const value = insert();
|
|
90
|
+
this.set(key, value);
|
|
91
|
+
return value;
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Helper to create an observer entry asynchronously.
|
|
97
|
+
* Separated to handle async operations cleanly.
|
|
98
|
+
*/
|
|
99
|
+
async function createObserverEntry(
|
|
100
|
+
config: MountConfig,
|
|
101
|
+
registryRoot: Node
|
|
102
|
+
): Promise<ObserverEntry> {
|
|
103
|
+
// Dynamically import to avoid circular dependency
|
|
104
|
+
const { MountObserver: MountObserverClass } = await import('./MountObserver.js');
|
|
105
|
+
const observer = new MountObserverClass(config);
|
|
106
|
+
await observer.observe(registryRoot);
|
|
107
|
+
return {
|
|
108
|
+
config,
|
|
109
|
+
registryRootRef: new WeakRef(registryRoot),
|
|
110
|
+
observer
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Get or create a mount observer for a specific registry + config + registry root combination.
|
|
116
|
+
* This function ensures that:
|
|
117
|
+
* 1. The config is registered with the registry's mountConfigRegistry
|
|
118
|
+
* 2. An observer exists for this specific registry root
|
|
119
|
+
* 3. All other registry roots with the same registry get observers for this config
|
|
120
|
+
* 4. All other configs get observers for this registry root
|
|
121
|
+
*
|
|
122
|
+
* @returns The ObserverEntry for the requested combination
|
|
123
|
+
*/
|
|
124
|
+
export async function getOrInsertObserverEntry(
|
|
125
|
+
registry: CustomElementRegistry,
|
|
126
|
+
config: MountConfig,
|
|
127
|
+
registryRoot: Node
|
|
128
|
+
): Promise<ObserverEntry> {
|
|
129
|
+
// Add config to the registry's config list (if not already there)
|
|
130
|
+
(registry as any).mountConfigRegistry.push(config);
|
|
131
|
+
|
|
132
|
+
// Get or create the nested map structure
|
|
133
|
+
const mountConfigMap = (getRegistryObservers()).getOrInsertComputed(registry, () => new Map());
|
|
134
|
+
const nodeToObserverMap = mountConfigMap.getOrInsertComputed(config, () => new WeakMap());
|
|
135
|
+
|
|
136
|
+
// Get or create the observer for this specific registry root
|
|
137
|
+
let observerEntry = nodeToObserverMap.get(registryRoot);
|
|
138
|
+
if (!observerEntry) {
|
|
139
|
+
observerEntry = await createObserverEntry(config, registryRoot);
|
|
140
|
+
nodeToObserverMap.set(registryRoot, observerEntry);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Track this registry root in the scopes set
|
|
144
|
+
const scopes = getRegistryScopes().getOrInsertComputed(registry, () => ({
|
|
145
|
+
weakSet: new WeakSet<Node>(),
|
|
146
|
+
setWeak: new Set<WeakRef<Node>>()
|
|
147
|
+
}));
|
|
148
|
+
|
|
149
|
+
// Add to tracking sets if not already present
|
|
150
|
+
if (!scopes.weakSet.has(registryRoot)) {
|
|
151
|
+
scopes.weakSet.add(registryRoot);
|
|
152
|
+
scopes.setWeak.add(new WeakRef(registryRoot));
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Get all configs for this registry
|
|
156
|
+
const configs = (registry as any).mountConfigRegistry.items;
|
|
157
|
+
|
|
158
|
+
// Iterate over all known registry roots for this registry
|
|
159
|
+
const arr = Array.from(scopes.setWeak) as WeakRef<Node>[];
|
|
160
|
+
for (const regRootRef of arr) {
|
|
161
|
+
const regRoot = regRootRef.deref();
|
|
162
|
+
if (regRoot === undefined) continue;
|
|
163
|
+
|
|
164
|
+
// For each config, ensure an observer exists for this registry root
|
|
165
|
+
for (const conf of configs) {
|
|
166
|
+
// Skip if this is the same config + root we just created
|
|
167
|
+
if (conf === config && registryRoot === regRoot) continue;
|
|
168
|
+
|
|
169
|
+
// Get or create observer for this conf + regRoot combination
|
|
170
|
+
// This won't cause infinite loop because we only create if missing
|
|
171
|
+
const confObserverMap = mountConfigMap.getOrInsertComputed(conf, () => new WeakMap());
|
|
172
|
+
let existingEntry = confObserverMap.get(regRoot);
|
|
173
|
+
if (!existingEntry) {
|
|
174
|
+
existingEntry = await createObserverEntry(conf, regRoot);
|
|
175
|
+
confObserverMap.set(regRoot, existingEntry);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return observerEntry;
|
|
181
|
+
}
|
package/connectionMonitor.js
CHANGED
|
@@ -47,7 +47,7 @@ export function setupConnectionMonitor(init, rootNodeRef, mountedElements, modul
|
|
|
47
47
|
modules,
|
|
48
48
|
observer: observer,
|
|
49
49
|
rootNode,
|
|
50
|
-
|
|
50
|
+
mountConfig: init
|
|
51
51
|
};
|
|
52
52
|
// Get all mounted elements from the WeakDual setWeak
|
|
53
53
|
const mountedElementsList = [];
|
package/connectionMonitor.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @param node - The starting node to check
|
|
7
7
|
* @returns The highest node with matching customElementRegistry, or null if node is invalid
|
|
8
8
|
*/
|
|
9
|
-
export function
|
|
9
|
+
export function getRegistryRoot(node) {
|
|
10
10
|
if (!node) {
|
|
11
11
|
return null;
|
|
12
12
|
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @param node - The starting node to check
|
|
7
7
|
* @returns The highest node with matching customElementRegistry, or null if node is invalid
|
|
8
8
|
*/
|
|
9
|
-
export function
|
|
9
|
+
export function getRegistryRoot(node: Node): Node | null {
|
|
10
10
|
if (!node) {
|
|
11
11
|
return null;
|
|
12
12
|
}
|
package/index.js
CHANGED
|
@@ -4,15 +4,20 @@ export { withScopePerimeter } from './withScopePerimeter.js';
|
|
|
4
4
|
export { emitMountedElementEvents } from './emitEvents.js';
|
|
5
5
|
export { arr } from './arr.js';
|
|
6
6
|
export { EvtRt } from './EvtRt.js';
|
|
7
|
-
export { DefineCustomElementHandler } from './
|
|
8
|
-
export { EnhanceMountedElementHandler } from './
|
|
7
|
+
export { DefineCustomElementHandler, DefineScopedCustomElementHandler } from './handlers/DefineCustomElement.js';
|
|
8
|
+
export { EnhanceMountedElementHandler } from './handlers/EnhanceMountedElement.js';
|
|
9
|
+
export { ScriptNoModuleHandler } from './handlers/ScriptNoModule.js';
|
|
10
|
+
export { MountObserverScriptHandler } from './handlers/MountObserverScript.js';
|
|
11
|
+
export { HoistTemplateHandler } from './handlers/HoistTemplate.js';
|
|
12
|
+
export { HTMLIncludeHandler } from './handlers/HTMLInclude.js';
|
|
13
|
+
export { upShadowSearch } from './upShadowSearch.js';
|
|
9
14
|
export { mountEventName, dismountEventName, disconnectEventName, loadEventName, mediamatchEventName, mediaunmatchEventName } from './Events.js';
|
|
10
15
|
// Register built-in handlers
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
import './EvtRt.js';
|
|
17
|
+
import './handlers/DefineCustomElement.js';
|
|
18
|
+
import './handlers/EnhanceMountedElement.js';
|
|
19
|
+
import './handlers/GenIds.js'; // Temporarily disabled due to missing dependency
|
|
20
|
+
import './handlers/ScriptNoModule.js';
|
|
21
|
+
import './handlers/MountObserverScript.js';
|
|
22
|
+
import './handlers/HoistTemplate.js';
|
|
23
|
+
import './handlers/HTMLInclude.js';
|
package/index.ts
CHANGED
|
@@ -4,8 +4,13 @@ export { withScopePerimeter } from './withScopePerimeter.js';
|
|
|
4
4
|
export { emitMountedElementEvents } from './emitEvents.js';
|
|
5
5
|
export { arr } from './arr.js';
|
|
6
6
|
export { EvtRt } from './EvtRt.js';
|
|
7
|
-
export { DefineCustomElementHandler } from './
|
|
8
|
-
export { EnhanceMountedElementHandler } from './
|
|
7
|
+
export { DefineCustomElementHandler, DefineScopedCustomElementHandler } from './handlers/DefineCustomElement.js';
|
|
8
|
+
export { EnhanceMountedElementHandler } from './handlers/EnhanceMountedElement.js';
|
|
9
|
+
export { ScriptNoModuleHandler } from './handlers/ScriptNoModule.js';
|
|
10
|
+
export { MountObserverScriptHandler } from './handlers/MountObserverScript.js';
|
|
11
|
+
export { HoistTemplateHandler } from './handlers/HoistTemplate.js';
|
|
12
|
+
export { HTMLIncludeHandler } from './handlers/HTMLInclude.js';
|
|
13
|
+
export { upShadowSearch } from './upShadowSearch.js';
|
|
9
14
|
export type {
|
|
10
15
|
MountConfig,
|
|
11
16
|
MountObserverOptions,
|
|
@@ -26,12 +31,12 @@ export {
|
|
|
26
31
|
} from './Events.js';
|
|
27
32
|
|
|
28
33
|
// Register built-in handlers
|
|
29
|
-
import
|
|
30
|
-
import
|
|
31
|
-
import
|
|
32
|
-
import
|
|
34
|
+
import './EvtRt.js';
|
|
35
|
+
import './handlers/DefineCustomElement.js';
|
|
36
|
+
import './handlers/EnhanceMountedElement.js';
|
|
37
|
+
import './handlers/GenIds.js'; // Temporarily disabled due to missing dependency
|
|
38
|
+
import './handlers/ScriptNoModule.js';
|
|
39
|
+
import './handlers/MountObserverScript.js';
|
|
40
|
+
import './handlers/HoistTemplate.js';
|
|
41
|
+
import './handlers/HTMLInclude.js';
|
|
33
42
|
|
|
34
|
-
MountObserver.define('builtIns.logToConsole', EvtRt);
|
|
35
|
-
MountObserver.define('builtIns.defineCustomElement', DefineCustomElementHandler);
|
|
36
|
-
MountObserver.define('buildIns.defineScopedCustomElement', DefineScopedCustomElementHandler);
|
|
37
|
-
MountObserver.define('builtIns.enhanceMountedElement', EnhanceMountedElementHandler);
|
package/mediaQuery.js
CHANGED
|
@@ -49,7 +49,7 @@ export function setupMediaQuery(init, rootNodeRef, mountedElements, modules, obs
|
|
|
49
49
|
modules,
|
|
50
50
|
observer: observer,
|
|
51
51
|
rootNode,
|
|
52
|
-
|
|
52
|
+
mountConfig: init
|
|
53
53
|
};
|
|
54
54
|
// Get all mounted elements from the WeakDual setWeak
|
|
55
55
|
const mountedElementsList = [];
|
package/mediaQuery.ts
CHANGED
package/observedRootHas.js
CHANGED
|
@@ -1,87 +1,87 @@
|
|
|
1
|
-
import { DismountEvent } from './Events.js';
|
|
2
|
-
export function setupObservedRootHas(init, rootNodeRef, mountedElements, modules, observer, processNode) {
|
|
3
|
-
const { whereObservedRootHas } = init;
|
|
4
|
-
if (!whereObservedRootHas) {
|
|
5
|
-
throw new Error('whereObservedRootHas is required');
|
|
6
|
-
}
|
|
7
|
-
const rootNode = rootNodeRef.deref();
|
|
8
|
-
if (!rootNode) {
|
|
9
|
-
throw new Error('Root node has been garbage collected');
|
|
10
|
-
}
|
|
11
|
-
// Get the element to query against
|
|
12
|
-
const rootElement = rootNode instanceof Element
|
|
13
|
-
? rootNode
|
|
14
|
-
: rootNode.documentElement || rootNode.host;
|
|
15
|
-
if (!rootElement) {
|
|
16
|
-
throw new Error('Could not determine root element for whereObservedRootHas');
|
|
17
|
-
}
|
|
18
|
-
// Track current state
|
|
19
|
-
let conditionMatches = !!rootElement.querySelector(whereObservedRootHas);
|
|
20
|
-
// Set up mutation observer to watch for changes
|
|
21
|
-
const mutationObserver = new MutationObserver(() => {
|
|
22
|
-
const previousMatches = conditionMatches;
|
|
23
|
-
conditionMatches = !!rootElement.querySelector(whereObservedRootHas);
|
|
24
|
-
if (conditionMatches && !previousMatches) {
|
|
25
|
-
// Condition now matches - process elements
|
|
26
|
-
handleConditionMatch();
|
|
27
|
-
}
|
|
28
|
-
else if (!conditionMatches && previousMatches) {
|
|
29
|
-
// Condition no longer matches - dismount all elements
|
|
30
|
-
handleConditionUnmatch();
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
function handleConditionMatch() {
|
|
34
|
-
// Process all elements in the observed node
|
|
35
|
-
const rootNode = rootNodeRef.deref();
|
|
36
|
-
if (rootNode) {
|
|
37
|
-
processNode(rootNode);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
function handleConditionUnmatch() {
|
|
41
|
-
// Dismount all currently mounted elements
|
|
42
|
-
const rootNode = rootNodeRef.deref();
|
|
43
|
-
if (!rootNode) {
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
const context = {
|
|
47
|
-
modules,
|
|
48
|
-
observer: observer,
|
|
49
|
-
rootNode,
|
|
50
|
-
MountConfig: init
|
|
51
|
-
};
|
|
52
|
-
// Get all mounted elements from the WeakDual setWeak
|
|
53
|
-
const mountedElementsList = [];
|
|
54
|
-
for (const ref of mountedElements.setWeak) {
|
|
55
|
-
const element = ref.deref();
|
|
56
|
-
if (element) {
|
|
57
|
-
mountedElementsList.push(element);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
// Dismount each element
|
|
61
|
-
for (const element of mountedElementsList) {
|
|
62
|
-
// Remove from both structures
|
|
63
|
-
mountedElements.weakSet.delete(element);
|
|
64
|
-
for (const ref of mountedElements.setWeak) {
|
|
65
|
-
if (ref.deref() === element) {
|
|
66
|
-
mountedElements.setWeak.delete(ref);
|
|
67
|
-
break;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
// Dispatch dismount event with reason
|
|
71
|
-
observer.dispatchEvent(new DismountEvent(element, 'observed-root-has-failed', init));
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
// Observe the root element for changes
|
|
75
|
-
mutationObserver.observe(rootElement, {
|
|
76
|
-
childList: true,
|
|
77
|
-
subtree: true,
|
|
78
|
-
attributes: true,
|
|
79
|
-
attributeOldValue: false
|
|
80
|
-
});
|
|
81
|
-
return {
|
|
82
|
-
conditionMatches,
|
|
83
|
-
cleanup: () => {
|
|
84
|
-
mutationObserver.disconnect();
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
|
-
}
|
|
1
|
+
import { DismountEvent } from './Events.js';
|
|
2
|
+
export function setupObservedRootHas(init, rootNodeRef, mountedElements, modules, observer, processNode) {
|
|
3
|
+
const { whereObservedRootHas } = init;
|
|
4
|
+
if (!whereObservedRootHas) {
|
|
5
|
+
throw new Error('whereObservedRootHas is required');
|
|
6
|
+
}
|
|
7
|
+
const rootNode = rootNodeRef.deref();
|
|
8
|
+
if (!rootNode) {
|
|
9
|
+
throw new Error('Root node has been garbage collected');
|
|
10
|
+
}
|
|
11
|
+
// Get the element to query against
|
|
12
|
+
const rootElement = rootNode instanceof Element
|
|
13
|
+
? rootNode
|
|
14
|
+
: rootNode.documentElement || rootNode.host;
|
|
15
|
+
if (!rootElement) {
|
|
16
|
+
throw new Error('Could not determine root element for whereObservedRootHas');
|
|
17
|
+
}
|
|
18
|
+
// Track current state
|
|
19
|
+
let conditionMatches = !!rootElement.querySelector(whereObservedRootHas);
|
|
20
|
+
// Set up mutation observer to watch for changes
|
|
21
|
+
const mutationObserver = new MutationObserver(() => {
|
|
22
|
+
const previousMatches = conditionMatches;
|
|
23
|
+
conditionMatches = !!rootElement.querySelector(whereObservedRootHas);
|
|
24
|
+
if (conditionMatches && !previousMatches) {
|
|
25
|
+
// Condition now matches - process elements
|
|
26
|
+
handleConditionMatch();
|
|
27
|
+
}
|
|
28
|
+
else if (!conditionMatches && previousMatches) {
|
|
29
|
+
// Condition no longer matches - dismount all elements
|
|
30
|
+
handleConditionUnmatch();
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
function handleConditionMatch() {
|
|
34
|
+
// Process all elements in the observed node
|
|
35
|
+
const rootNode = rootNodeRef.deref();
|
|
36
|
+
if (rootNode) {
|
|
37
|
+
processNode(rootNode);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function handleConditionUnmatch() {
|
|
41
|
+
// Dismount all currently mounted elements
|
|
42
|
+
const rootNode = rootNodeRef.deref();
|
|
43
|
+
if (!rootNode) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const context = {
|
|
47
|
+
modules,
|
|
48
|
+
observer: observer,
|
|
49
|
+
rootNode,
|
|
50
|
+
MountConfig: init
|
|
51
|
+
};
|
|
52
|
+
// Get all mounted elements from the WeakDual setWeak
|
|
53
|
+
const mountedElementsList = [];
|
|
54
|
+
for (const ref of mountedElements.setWeak) {
|
|
55
|
+
const element = ref.deref();
|
|
56
|
+
if (element) {
|
|
57
|
+
mountedElementsList.push(element);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Dismount each element
|
|
61
|
+
for (const element of mountedElementsList) {
|
|
62
|
+
// Remove from both structures
|
|
63
|
+
mountedElements.weakSet.delete(element);
|
|
64
|
+
for (const ref of mountedElements.setWeak) {
|
|
65
|
+
if (ref.deref() === element) {
|
|
66
|
+
mountedElements.setWeak.delete(ref);
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Dispatch dismount event with reason
|
|
71
|
+
observer.dispatchEvent(new DismountEvent(element, 'observed-root-has-failed', init));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Observe the root element for changes
|
|
75
|
+
mutationObserver.observe(rootElement, {
|
|
76
|
+
childList: true,
|
|
77
|
+
subtree: true,
|
|
78
|
+
attributes: true,
|
|
79
|
+
attributeOldValue: false
|
|
80
|
+
});
|
|
81
|
+
return {
|
|
82
|
+
conditionMatches,
|
|
83
|
+
cleanup: () => {
|
|
84
|
+
mutationObserver.disconnect();
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
}
|