@async/framework 0.11.14 → 0.11.15
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/CHANGELOG.md +30 -3
- package/README.md +92 -1
- package/browser.d.ts +42 -2
- package/browser.js +288 -16
- package/browser.min.js +1 -1
- package/browser.ts +288 -16
- package/browser.umd.js +288 -16
- package/browser.umd.min.js +1 -1
- package/framework.d.ts +42 -2
- package/framework.ts +288 -16
- package/package.json +5 -72
- package/server.js +288 -16
package/browser.umd.js
CHANGED
|
@@ -1172,6 +1172,7 @@
|
|
|
1172
1172
|
async: ["async:"],
|
|
1173
1173
|
class: ["class:"],
|
|
1174
1174
|
signal: ["signal:"],
|
|
1175
|
+
intersect: ["intersect:"],
|
|
1175
1176
|
on: ["on:"]
|
|
1176
1177
|
});
|
|
1177
1178
|
|
|
@@ -1184,6 +1185,7 @@
|
|
|
1184
1185
|
async: normalizePrefixes(config.async, defaultPrefixes.async),
|
|
1185
1186
|
class: normalizePrefixes(config.class, defaultPrefixes.class),
|
|
1186
1187
|
signal: normalizePrefixes(config.signal, defaultPrefixes.signal),
|
|
1188
|
+
intersect: normalizePrefixes(config.intersect, defaultPrefixes.intersect),
|
|
1187
1189
|
on: normalizePrefixes(config.on, defaultPrefixes.on)
|
|
1188
1190
|
};
|
|
1189
1191
|
}
|
|
@@ -2149,6 +2151,7 @@
|
|
|
2149
2151
|
const cleanups = [];
|
|
2150
2152
|
const attachHooks = [];
|
|
2151
2153
|
const visibleHooks = [];
|
|
2154
|
+
const intersectionHooks = [];
|
|
2152
2155
|
const destroyHooks = [];
|
|
2153
2156
|
const bindingIds = [];
|
|
2154
2157
|
const templateOptions = {
|
|
@@ -2170,6 +2173,7 @@
|
|
|
2170
2173
|
cleanups,
|
|
2171
2174
|
attachHooks,
|
|
2172
2175
|
visibleHooks,
|
|
2176
|
+
intersectionHooks,
|
|
2173
2177
|
destroyHooks,
|
|
2174
2178
|
renderScopedTemplate
|
|
2175
2179
|
});
|
|
@@ -2221,6 +2225,15 @@
|
|
|
2221
2225
|
cleanups.push(cleanup);
|
|
2222
2226
|
}
|
|
2223
2227
|
},
|
|
2228
|
+
intersection(target, observeIntersection) {
|
|
2229
|
+
if (intersectionHooks.length === 0) {
|
|
2230
|
+
return;
|
|
2231
|
+
}
|
|
2232
|
+
for (let index = 0; index < intersectionHooks.length; index += 1) {
|
|
2233
|
+
const hook = intersectionHooks[index];
|
|
2234
|
+
hook(target, observeIntersection);
|
|
2235
|
+
}
|
|
2236
|
+
},
|
|
2224
2237
|
cleanup() {
|
|
2225
2238
|
while (destroyHooks.length > 0) {
|
|
2226
2239
|
destroyHooks.pop()?.();
|
|
@@ -2250,7 +2263,7 @@
|
|
|
2250
2263
|
}
|
|
2251
2264
|
}
|
|
2252
2265
|
|
|
2253
|
-
function createComponentContext({ runtime, scope, cleanups, attachHooks, visibleHooks, destroyHooks, renderScopedTemplate }) {
|
|
2266
|
+
function createComponentContext({ runtime, scope, cleanups, attachHooks, visibleHooks, intersectionHooks, destroyHooks, renderScopedTemplate }) {
|
|
2254
2267
|
const { signals, handlers, loader, server, router, cache, scheduler } = runtime;
|
|
2255
2268
|
const generatedHandlers = new WeakMap();
|
|
2256
2269
|
let generatedHandlerCounter = 0;
|
|
@@ -2338,6 +2351,7 @@
|
|
|
2338
2351
|
cleanups.push(child.cleanup);
|
|
2339
2352
|
attachHooks.push((target) => child.attach(target));
|
|
2340
2353
|
visibleHooks.push((target) => child.visible(target, loader._observeVisible));
|
|
2354
|
+
intersectionHooks.push((target) => child.intersection(target, loader._observeIntersection));
|
|
2341
2355
|
return rawHtml(child.html);
|
|
2342
2356
|
},
|
|
2343
2357
|
|
|
@@ -2361,14 +2375,22 @@
|
|
|
2361
2375
|
return rawHtml(chunks.join(""));
|
|
2362
2376
|
},
|
|
2363
2377
|
|
|
2364
|
-
on(eventName,
|
|
2378
|
+
on(eventName, optionsOrFn, maybeFn) {
|
|
2365
2379
|
if (typeof eventName !== "string" || eventName.length === 0) {
|
|
2366
2380
|
throw new TypeError("Component lifecycle event must be a non-empty string.");
|
|
2367
2381
|
}
|
|
2368
|
-
|
|
2382
|
+
const event = eventName === "mount" ? "attach" : eventName;
|
|
2383
|
+
if (event === "intersect") {
|
|
2384
|
+
const { options, fn } = normalizeOptionsCallback(`Component lifecycle "${eventName}"`, optionsOrFn, maybeFn);
|
|
2385
|
+
intersectionHooks.push((target) => {
|
|
2386
|
+
context.intersect(target, options, fn);
|
|
2387
|
+
});
|
|
2388
|
+
return;
|
|
2389
|
+
}
|
|
2390
|
+
if (maybeFn !== undefined || typeof optionsOrFn !== "function") {
|
|
2369
2391
|
throw new TypeError(`Component lifecycle "${eventName}" requires a function.`);
|
|
2370
2392
|
}
|
|
2371
|
-
const
|
|
2393
|
+
const fn = optionsOrFn;
|
|
2372
2394
|
if (event === "attach") {
|
|
2373
2395
|
attachHooks.push((target) => fn.call(context, target));
|
|
2374
2396
|
return;
|
|
@@ -2390,6 +2412,18 @@
|
|
|
2390
2412
|
|
|
2391
2413
|
onVisible(fn) {
|
|
2392
2414
|
context.on("visible", fn);
|
|
2415
|
+
},
|
|
2416
|
+
|
|
2417
|
+
intersect(target, optionsOrFn, maybeFn) {
|
|
2418
|
+
const { options, fn } = normalizeOptionsCallback("this.intersect(target, ...)", optionsOrFn, maybeFn);
|
|
2419
|
+
const cleanup = loader._observeIntersection(target, (event) => fn.call(context, event), {
|
|
2420
|
+
...options,
|
|
2421
|
+
scope
|
|
2422
|
+
});
|
|
2423
|
+
if (typeof cleanup === "function") {
|
|
2424
|
+
cleanups.push(cleanup);
|
|
2425
|
+
}
|
|
2426
|
+
return cleanup;
|
|
2393
2427
|
}
|
|
2394
2428
|
};
|
|
2395
2429
|
|
|
@@ -2405,6 +2439,16 @@
|
|
|
2405
2439
|
}
|
|
2406
2440
|
}
|
|
2407
2441
|
|
|
2442
|
+
function normalizeOptionsCallback(label, optionsOrFn, maybeFn) {
|
|
2443
|
+
if (typeof optionsOrFn === "function" && maybeFn === undefined) {
|
|
2444
|
+
return { options: {}, fn: optionsOrFn };
|
|
2445
|
+
}
|
|
2446
|
+
if ((optionsOrFn == null || (typeof optionsOrFn === "object" && !Array.isArray(optionsOrFn))) && typeof maybeFn === "function") {
|
|
2447
|
+
return { options: optionsOrFn ?? {}, fn: maybeFn };
|
|
2448
|
+
}
|
|
2449
|
+
throw new TypeError(`${label} requires (fn) or (options, fn).`);
|
|
2450
|
+
}
|
|
2451
|
+
|
|
2408
2452
|
function scoped(scope, name) {
|
|
2409
2453
|
if (typeof name !== "string" || name.length === 0) {
|
|
2410
2454
|
throw new TypeError("Scoped signal or handler name must be a non-empty string.");
|
|
@@ -3500,6 +3544,7 @@
|
|
|
3500
3544
|
const signalBindings = new WeakMap();
|
|
3501
3545
|
const mountedElements = new WeakSet();
|
|
3502
3546
|
const visibleElements = new WeakSet();
|
|
3547
|
+
const intersectionBindings = new WeakMap();
|
|
3503
3548
|
const boundaryState = new WeakMap();
|
|
3504
3549
|
const renderingBoundaries = new WeakSet();
|
|
3505
3550
|
const inlineBindings = new Map();
|
|
@@ -3563,6 +3608,7 @@
|
|
|
3563
3608
|
api.scan(target);
|
|
3564
3609
|
rendered.mount(target);
|
|
3565
3610
|
rendered.visible(target, api._observeVisible);
|
|
3611
|
+
rendered.intersection(target, api._observeIntersection);
|
|
3566
3612
|
addCleanup(rendered.cleanup, target, "children");
|
|
3567
3613
|
return rendered;
|
|
3568
3614
|
},
|
|
@@ -3586,6 +3632,10 @@
|
|
|
3586
3632
|
return observeVisible(target, fn);
|
|
3587
3633
|
},
|
|
3588
3634
|
|
|
3635
|
+
_observeIntersection(target, fn, options = {}) {
|
|
3636
|
+
return observeIntersection(target, fn, options);
|
|
3637
|
+
},
|
|
3638
|
+
|
|
3589
3639
|
_registerBinding(value) {
|
|
3590
3640
|
const id = `${inlineBindingPrefix}${++inlineBindingCounter}`;
|
|
3591
3641
|
inlineBindings.set(id, value);
|
|
@@ -3617,7 +3667,7 @@
|
|
|
3617
3667
|
if (!eventName) {
|
|
3618
3668
|
continue;
|
|
3619
3669
|
}
|
|
3620
|
-
if (eventName === "attach" || eventName === "mount" || eventName === "visible") {
|
|
3670
|
+
if (eventName === "attach" || eventName === "mount" || eventName === "visible" || eventName === "intersect") {
|
|
3621
3671
|
continue;
|
|
3622
3672
|
}
|
|
3623
3673
|
bindEvent(element, eventName, element.getAttribute(name));
|
|
@@ -3890,6 +3940,25 @@
|
|
|
3890
3940
|
visibleElements.add(element);
|
|
3891
3941
|
addCleanup(observeVisible(element, () => scheduleLifecycle(element, () => runPseudo(element, ref), `visible:${ref}`)), element);
|
|
3892
3942
|
}
|
|
3943
|
+
|
|
3944
|
+
for (const element of elementsIn(scope)) {
|
|
3945
|
+
const ref = readAttribute(element, attributeConfig, "on", "intersect");
|
|
3946
|
+
if (ref == null) {
|
|
3947
|
+
continue;
|
|
3948
|
+
}
|
|
3949
|
+
const options = readIntersectionOptions(element);
|
|
3950
|
+
const key = `intersect:${ref}:${serializeIntersectionOptions(options)}`;
|
|
3951
|
+
const bound = intersectionBindings.get(element) ?? new Set();
|
|
3952
|
+
if (bound.has(key)) {
|
|
3953
|
+
continue;
|
|
3954
|
+
}
|
|
3955
|
+
bound.add(key);
|
|
3956
|
+
intersectionBindings.set(element, bound);
|
|
3957
|
+
addCleanup(observeIntersection(element, (event) => runPseudo(element, ref, event), {
|
|
3958
|
+
...options,
|
|
3959
|
+
key
|
|
3960
|
+
}), element);
|
|
3961
|
+
}
|
|
3893
3962
|
}
|
|
3894
3963
|
|
|
3895
3964
|
function readPseudoRefs(element, names) {
|
|
@@ -3903,7 +3972,7 @@
|
|
|
3903
3972
|
return refs;
|
|
3904
3973
|
}
|
|
3905
3974
|
|
|
3906
|
-
async function runPseudo(element, ref) {
|
|
3975
|
+
async function runPseudo(element, ref, context = {}) {
|
|
3907
3976
|
try {
|
|
3908
3977
|
const results = await handlerRegistry.run(ref, {
|
|
3909
3978
|
signals: signalRegistry,
|
|
@@ -3915,7 +3984,8 @@
|
|
|
3915
3984
|
scheduler: schedulerInstance,
|
|
3916
3985
|
element,
|
|
3917
3986
|
el: element,
|
|
3918
|
-
root: rootNode
|
|
3987
|
+
root: rootNode,
|
|
3988
|
+
...context
|
|
3919
3989
|
});
|
|
3920
3990
|
for (const result of results) {
|
|
3921
3991
|
if (typeof result === "function") {
|
|
@@ -3928,28 +3998,230 @@
|
|
|
3928
3998
|
}
|
|
3929
3999
|
|
|
3930
4000
|
function observeVisible(target, fn) {
|
|
4001
|
+
return observeIntersection(target, (event) => {
|
|
4002
|
+
if (event.isIntersecting) {
|
|
4003
|
+
fn(target);
|
|
4004
|
+
}
|
|
4005
|
+
}, {
|
|
4006
|
+
once: true,
|
|
4007
|
+
threshold: 0
|
|
4008
|
+
});
|
|
4009
|
+
}
|
|
4010
|
+
|
|
4011
|
+
function observeIntersection(target, fn, options = {}) {
|
|
4012
|
+
if (typeof fn !== "function") {
|
|
4013
|
+
throw new TypeError("observeIntersection(target, fn) requires a callback.");
|
|
4014
|
+
}
|
|
4015
|
+
const normalized = normalizeIntersectionOptions(target, options);
|
|
3931
4016
|
const ownerWindow = target.ownerDocument?.defaultView ?? globalThis;
|
|
3932
4017
|
const Observer = ownerWindow.IntersectionObserver ?? globalThis.IntersectionObserver;
|
|
3933
4018
|
if (!Observer) {
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
4019
|
+
let cleaned = false;
|
|
4020
|
+
const event = createIntersectionEvent({
|
|
4021
|
+
target,
|
|
4022
|
+
root: normalized.root,
|
|
4023
|
+
entry: createFallbackIntersectionEntry(target),
|
|
4024
|
+
observer: null,
|
|
4025
|
+
unsupported: true
|
|
4026
|
+
});
|
|
4027
|
+
const cancel = schedulerInstance.enqueue("lifecycle", () => {
|
|
4028
|
+
if (!cleaned && !destroyed) {
|
|
4029
|
+
fn(event);
|
|
3937
4030
|
}
|
|
3938
4031
|
}, {
|
|
3939
|
-
scope:
|
|
3940
|
-
key: "
|
|
4032
|
+
scope: normalized.scope,
|
|
4033
|
+
key: normalized.key ?? "intersect:fallback"
|
|
3941
4034
|
});
|
|
3942
|
-
return () => {
|
|
4035
|
+
return () => {
|
|
4036
|
+
cleaned = true;
|
|
4037
|
+
cancel?.();
|
|
4038
|
+
};
|
|
3943
4039
|
}
|
|
3944
4040
|
|
|
4041
|
+
let cleaned = false;
|
|
4042
|
+
let stopped = false;
|
|
3945
4043
|
const observer = new Observer((entries) => {
|
|
3946
|
-
if (
|
|
4044
|
+
if (cleaned || stopped || destroyed) {
|
|
4045
|
+
return;
|
|
4046
|
+
}
|
|
4047
|
+
const observedEntries = entries.filter((entry) => entry.target === target);
|
|
4048
|
+
const targetEntries = observedEntries.length > 0 ? observedEntries : entries;
|
|
4049
|
+
const entry = targetEntries[0];
|
|
4050
|
+
if (!entry) {
|
|
4051
|
+
return;
|
|
4052
|
+
}
|
|
4053
|
+
const event = createIntersectionEvent({
|
|
4054
|
+
target,
|
|
4055
|
+
root: normalized.root,
|
|
4056
|
+
entry,
|
|
4057
|
+
entries: targetEntries,
|
|
4058
|
+
observer,
|
|
4059
|
+
unsupported: false
|
|
4060
|
+
});
|
|
4061
|
+
if (normalized.once && event.isIntersecting) {
|
|
4062
|
+
stopped = true;
|
|
3947
4063
|
observer.disconnect();
|
|
3948
|
-
fn(target);
|
|
3949
4064
|
}
|
|
4065
|
+
runIntersectionCallback(fn, event, normalized, () => !cleaned);
|
|
4066
|
+
}, {
|
|
4067
|
+
root: normalized.root,
|
|
4068
|
+
rootMargin: normalized.rootMargin,
|
|
4069
|
+
threshold: normalized.threshold
|
|
3950
4070
|
});
|
|
3951
4071
|
observer.observe(target);
|
|
3952
|
-
return () =>
|
|
4072
|
+
return () => {
|
|
4073
|
+
if (cleaned) {
|
|
4074
|
+
return;
|
|
4075
|
+
}
|
|
4076
|
+
cleaned = true;
|
|
4077
|
+
stopped = true;
|
|
4078
|
+
observer.disconnect();
|
|
4079
|
+
};
|
|
4080
|
+
}
|
|
4081
|
+
|
|
4082
|
+
function readIntersectionOptions(element) {
|
|
4083
|
+
const options = {};
|
|
4084
|
+
const threshold = readAttribute(element, attributeConfig, "intersect", "threshold");
|
|
4085
|
+
if (threshold != null) {
|
|
4086
|
+
options.threshold = parseIntersectionThreshold(threshold);
|
|
4087
|
+
}
|
|
4088
|
+
const rootMargin = readAttribute(element, attributeConfig, "intersect", "root-margin")
|
|
4089
|
+
?? readAttribute(element, attributeConfig, "intersect", "rootMargin");
|
|
4090
|
+
if (rootMargin != null) {
|
|
4091
|
+
options.rootMargin = rootMargin;
|
|
4092
|
+
}
|
|
4093
|
+
const once = readAttribute(element, attributeConfig, "intersect", "once");
|
|
4094
|
+
if (once != null) {
|
|
4095
|
+
options.once = parseBooleanAttribute(once);
|
|
4096
|
+
}
|
|
4097
|
+
return options;
|
|
4098
|
+
}
|
|
4099
|
+
|
|
4100
|
+
function parseIntersectionThreshold(value) {
|
|
4101
|
+
const parts = String(value).split(",").map((part) => part.trim()).filter(Boolean);
|
|
4102
|
+
if (parts.length === 0) {
|
|
4103
|
+
throw new TypeError("intersect:threshold must include a number from 0 to 1.");
|
|
4104
|
+
}
|
|
4105
|
+
const thresholds = parts.map((part) => {
|
|
4106
|
+
const number = Number(part);
|
|
4107
|
+
return validateIntersectionThreshold(number);
|
|
4108
|
+
});
|
|
4109
|
+
return thresholds.length === 1 ? thresholds[0] : thresholds;
|
|
4110
|
+
}
|
|
4111
|
+
|
|
4112
|
+
function parseBooleanAttribute(value) {
|
|
4113
|
+
const normalized = String(value).trim().toLowerCase();
|
|
4114
|
+
return normalized === "" || normalized === "true" || normalized === "1";
|
|
4115
|
+
}
|
|
4116
|
+
|
|
4117
|
+
function serializeIntersectionOptions(options) {
|
|
4118
|
+
return JSON.stringify({
|
|
4119
|
+
rootMargin: options.rootMargin ?? "0px",
|
|
4120
|
+
threshold: options.threshold ?? 0,
|
|
4121
|
+
once: Boolean(options.once)
|
|
4122
|
+
});
|
|
4123
|
+
}
|
|
4124
|
+
|
|
4125
|
+
function normalizeIntersectionOptions(target, options) {
|
|
4126
|
+
const ownerWindow = target?.ownerDocument?.defaultView ?? globalThis;
|
|
4127
|
+
if (!isElement(target, ownerWindow)) {
|
|
4128
|
+
throw new TypeError("Intersection target must be an Element.");
|
|
4129
|
+
}
|
|
4130
|
+
const root = options.root ?? null;
|
|
4131
|
+
if (root !== null && !isElement(root, ownerWindow) && !isDocument(root, ownerWindow)) {
|
|
4132
|
+
throw new TypeError("Intersection root must be an Element, Document, or null.");
|
|
4133
|
+
}
|
|
4134
|
+
const rootMargin = options.rootMargin ?? "0px";
|
|
4135
|
+
if (typeof rootMargin !== "string") {
|
|
4136
|
+
throw new TypeError("Intersection rootMargin must be a string.");
|
|
4137
|
+
}
|
|
4138
|
+
const threshold = normalizeIntersectionThreshold(options.threshold ?? 0);
|
|
4139
|
+
const schedule = options.schedule ?? "lifecycle";
|
|
4140
|
+
if (schedule !== "lifecycle" && schedule !== "sync") {
|
|
4141
|
+
throw new TypeError('Intersection schedule must be "lifecycle" or "sync".');
|
|
4142
|
+
}
|
|
4143
|
+
return {
|
|
4144
|
+
root,
|
|
4145
|
+
rootMargin,
|
|
4146
|
+
threshold,
|
|
4147
|
+
once: Boolean(options.once),
|
|
4148
|
+
schedule,
|
|
4149
|
+
scope: options.scope ?? target,
|
|
4150
|
+
key: options.key
|
|
4151
|
+
};
|
|
4152
|
+
}
|
|
4153
|
+
|
|
4154
|
+
function normalizeIntersectionThreshold(threshold) {
|
|
4155
|
+
if (Array.isArray(threshold)) {
|
|
4156
|
+
return threshold.map(validateIntersectionThreshold);
|
|
4157
|
+
}
|
|
4158
|
+
return validateIntersectionThreshold(threshold);
|
|
4159
|
+
}
|
|
4160
|
+
|
|
4161
|
+
function validateIntersectionThreshold(value) {
|
|
4162
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0 || value > 1) {
|
|
4163
|
+
throw new TypeError("Intersection threshold must be a number from 0 to 1.");
|
|
4164
|
+
}
|
|
4165
|
+
return value;
|
|
4166
|
+
}
|
|
4167
|
+
|
|
4168
|
+
function runIntersectionCallback(fn, event, options, isActive = () => true) {
|
|
4169
|
+
if (options.schedule === "sync") {
|
|
4170
|
+
if (isActive()) {
|
|
4171
|
+
fn(event);
|
|
4172
|
+
}
|
|
4173
|
+
return;
|
|
4174
|
+
}
|
|
4175
|
+
schedulerInstance.enqueue("lifecycle", () => {
|
|
4176
|
+
if (!destroyed && isActive()) {
|
|
4177
|
+
fn(event);
|
|
4178
|
+
}
|
|
4179
|
+
}, {
|
|
4180
|
+
scope: options.scope,
|
|
4181
|
+
key: options.key
|
|
4182
|
+
});
|
|
4183
|
+
}
|
|
4184
|
+
|
|
4185
|
+
function createIntersectionEvent({ target, root, entry, entries = [entry], observer, unsupported }) {
|
|
4186
|
+
const isIntersecting = Boolean(entry?.isIntersecting);
|
|
4187
|
+
const intersectionRatio = typeof entry?.intersectionRatio === "number"
|
|
4188
|
+
? entry.intersectionRatio
|
|
4189
|
+
: (isIntersecting ? 1 : 0);
|
|
4190
|
+
return {
|
|
4191
|
+
target,
|
|
4192
|
+
element: target,
|
|
4193
|
+
el: target,
|
|
4194
|
+
root: root ?? rootNode,
|
|
4195
|
+
entry,
|
|
4196
|
+
entries,
|
|
4197
|
+
observer,
|
|
4198
|
+
isIntersecting,
|
|
4199
|
+
intersectionRatio,
|
|
4200
|
+
unsupported: Boolean(unsupported)
|
|
4201
|
+
};
|
|
4202
|
+
}
|
|
4203
|
+
|
|
4204
|
+
function createFallbackIntersectionEntry(target) {
|
|
4205
|
+
const rect = target.getBoundingClientRect?.() ?? null;
|
|
4206
|
+
return {
|
|
4207
|
+
target,
|
|
4208
|
+
isIntersecting: true,
|
|
4209
|
+
intersectionRatio: 1,
|
|
4210
|
+
time: 0,
|
|
4211
|
+
rootBounds: null,
|
|
4212
|
+
boundingClientRect: rect,
|
|
4213
|
+
intersectionRect: rect
|
|
4214
|
+
};
|
|
4215
|
+
}
|
|
4216
|
+
|
|
4217
|
+
function isElement(value, ownerWindow = globalThis) {
|
|
4218
|
+
const ElementRef = ownerWindow.Element ?? globalThis.Element;
|
|
4219
|
+
return Boolean(ElementRef && value instanceof ElementRef);
|
|
4220
|
+
}
|
|
4221
|
+
|
|
4222
|
+
function isDocument(value, ownerWindow = globalThis) {
|
|
4223
|
+
const DocumentRef = ownerWindow.Document ?? globalThis.Document;
|
|
4224
|
+
return Boolean(DocumentRef && value instanceof DocumentRef);
|
|
3953
4225
|
}
|
|
3954
4226
|
|
|
3955
4227
|
function assertActive() {
|