@microsoft/webui-framework 0.0.28 → 0.0.30
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/README.md +20 -2
- package/dist/decorators.js +42 -8
- package/dist/element/style-catalog.d.ts +33 -0
- package/dist/element/style-catalog.js +154 -0
- package/dist/element/styles.d.ts +2 -29
- package/dist/element/styles.js +4 -157
- package/dist/element.d.ts +12 -0
- package/dist/element.js +122 -1
- package/dist/lifecycle.js +4 -0
- package/dist/static-host.js +2 -1
- package/dist/streaming-bootstrap.js +2 -2
- package/dist/streaming-deferred.js +44 -15
- package/dist/streaming-install.js +3 -2
- package/dist/streaming-mode.d.ts +2 -1
- package/dist/streaming-mode.js +4 -1
- package/dist/streaming-template-hosts.d.ts +5 -0
- package/dist/streaming-template-hosts.js +39 -0
- package/dist/template-content.d.ts +1 -0
- package/dist/template-content.js +6 -2
- package/dist/template-element.d.ts +4 -2
- package/dist/template-element.js +66 -47
- package/dist/template-registry.d.ts +29 -0
- package/dist/template-registry.js +228 -0
- package/dist/template.d.ts +1 -25
- package/dist/template.js +4 -206
- package/dist/trusted-types-policy.d.ts +4 -0
- package/dist/trusted-types-policy.js +62 -0
- package/package.json +5 -5
package/dist/element.js
CHANGED
|
@@ -7,6 +7,9 @@ const RENDER_ATTR = 'w-render';
|
|
|
7
7
|
const HYDRATE_EAGER = 'eager';
|
|
8
8
|
const INTERACTION_HYDRATION = 3;
|
|
9
9
|
const LAZY_RENDER_INTERACTION = 4;
|
|
10
|
+
const AUTHORED_LIVE = 1;
|
|
11
|
+
const AUTHORED_PENDING = 2;
|
|
12
|
+
const AUTHORED_FLUSHING = 4;
|
|
10
13
|
const DEV = typeof __WEBUI_DEV__ === 'undefined' || __WEBUI_DEV__;
|
|
11
14
|
let warnedMissingLazyHydrationEntry = false;
|
|
12
15
|
function warnMissingLazyHydrationEntry(tag, policy) {
|
|
@@ -22,6 +25,121 @@ function warnMissingLazyHydrationEntry(tag, policy) {
|
|
|
22
25
|
'your component definitions to enable visibility-deferred hydration.');
|
|
23
26
|
}
|
|
24
27
|
export class WebUIElement extends TemplateElement {
|
|
28
|
+
constructor() {
|
|
29
|
+
super();
|
|
30
|
+
const names = getObservableNames(this.constructor);
|
|
31
|
+
for (const name of names) {
|
|
32
|
+
if (!Object.prototype.hasOwnProperty.call(this, name))
|
|
33
|
+
continue;
|
|
34
|
+
(this.$preUpgradeProperties ??= new Map()).set(name, this[name]);
|
|
35
|
+
delete this[name];
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
connectedCallback() {
|
|
39
|
+
const properties = this.$preUpgradeProperties;
|
|
40
|
+
if (properties) {
|
|
41
|
+
this.$preUpgradeProperties = undefined;
|
|
42
|
+
for (const [name, value] of properties) {
|
|
43
|
+
this[name] = value;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
super.connectedCallback();
|
|
47
|
+
}
|
|
48
|
+
$destroy() {
|
|
49
|
+
if (this.$authoredPhase !== undefined)
|
|
50
|
+
this.$authoredPhase &= ~AUTHORED_LIVE;
|
|
51
|
+
super.$destroy();
|
|
52
|
+
}
|
|
53
|
+
$recordPropertyChange(name, oldValue) {
|
|
54
|
+
if (this.$authoredPhase === undefined)
|
|
55
|
+
return;
|
|
56
|
+
const changes = this.$pendingPropertyChanges;
|
|
57
|
+
if ((this.$authoredPhase & AUTHORED_LIVE) && this.$canRunAuthoredEffects()) {
|
|
58
|
+
if (changes?.has(name)) {
|
|
59
|
+
oldValue = changes.get(name);
|
|
60
|
+
changes.delete(name);
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
this.$invokePropertyChange(name, oldValue);
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
this.$releasePropertyChanges();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
const queued = changes ?? (this.$pendingPropertyChanges = new Map());
|
|
71
|
+
if (!queued.has(name))
|
|
72
|
+
queued.set(name, oldValue);
|
|
73
|
+
this.$authoredPhase |= AUTHORED_PENDING;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
$reconcileAuthoredState() {
|
|
77
|
+
if (!this.$canRunAuthoredEffects())
|
|
78
|
+
return !this.$pendingPropertyChanges;
|
|
79
|
+
if (this.$authoredPhase === undefined) {
|
|
80
|
+
const names = getObservableNames(this.constructor);
|
|
81
|
+
for (const name of names) {
|
|
82
|
+
if (typeof this[`${name}Changed`] !== 'function')
|
|
83
|
+
continue;
|
|
84
|
+
this.$authoredPhase = AUTHORED_LIVE;
|
|
85
|
+
if (Object.prototype.hasOwnProperty.call(this, `_${name}`)) {
|
|
86
|
+
(this.$pendingPropertyChanges ??= new Map()).set(name, undefined);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (this.$authoredPhase === undefined)
|
|
91
|
+
return true;
|
|
92
|
+
this.$authoredPhase |= AUTHORED_LIVE;
|
|
93
|
+
if (this.$authoredPhase & AUTHORED_FLUSHING)
|
|
94
|
+
return false;
|
|
95
|
+
if (this.$pendingPropertyChanges) {
|
|
96
|
+
this.$authoredPhase |= AUTHORED_PENDING;
|
|
97
|
+
this.$flushAuthoredChanges();
|
|
98
|
+
}
|
|
99
|
+
return !this.$pendingPropertyChanges;
|
|
100
|
+
}
|
|
101
|
+
$flushUpdates() {
|
|
102
|
+
if (this.$pendingPropertyChanges)
|
|
103
|
+
this.$notifyHydrated();
|
|
104
|
+
super.$flushUpdates();
|
|
105
|
+
}
|
|
106
|
+
$flushAuthoredChanges() {
|
|
107
|
+
const changes = this.$pendingPropertyChanges;
|
|
108
|
+
if (!changes || !this.$canRunAuthoredEffects())
|
|
109
|
+
return;
|
|
110
|
+
this.$authoredPhase = AUTHORED_LIVE | AUTHORED_PENDING | AUTHORED_FLUSHING;
|
|
111
|
+
try {
|
|
112
|
+
for (const [name, oldValue] of changes) {
|
|
113
|
+
if (!this.$canRunAuthoredEffects()) {
|
|
114
|
+
this.$authoredPhase &= ~AUTHORED_LIVE;
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
changes.delete(name);
|
|
118
|
+
this.$invokePropertyChange(name, oldValue);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
finally {
|
|
122
|
+
this.$authoredPhase &= ~AUTHORED_FLUSHING;
|
|
123
|
+
this.$releasePropertyChanges();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
$invokePropertyChange(name, oldValue) {
|
|
127
|
+
const value = this[name];
|
|
128
|
+
if (Object.is(oldValue, value))
|
|
129
|
+
return;
|
|
130
|
+
const callback = this[`${name}Changed`];
|
|
131
|
+
if (typeof callback === 'function') {
|
|
132
|
+
callback.call(this, oldValue, value);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
$releasePropertyChanges() {
|
|
136
|
+
const phase = this.$authoredPhase;
|
|
137
|
+
if (phase !== undefined && this.$pendingPropertyChanges?.size === 0 &&
|
|
138
|
+
!(phase & AUTHORED_FLUSHING)) {
|
|
139
|
+
this.$pendingPropertyChanges = undefined;
|
|
140
|
+
this.$authoredPhase = phase & ~AUTHORED_PENDING;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
25
143
|
$shouldDeferSSRHydration(meta) {
|
|
26
144
|
this.$lazyHydrationMode = this.$resolveLazyHydrationMode(meta);
|
|
27
145
|
return this.$lazyHydrationMode !== undefined;
|
|
@@ -90,6 +208,8 @@ export class WebUIElement extends TemplateElement {
|
|
|
90
208
|
this.$activateDeferredSSR(state);
|
|
91
209
|
}
|
|
92
210
|
disconnectedCallback() {
|
|
211
|
+
if (this.$authoredPhase !== undefined)
|
|
212
|
+
this.$authoredPhase &= ~AUTHORED_LIVE;
|
|
93
213
|
if (this.$lazyHydrationMode !== undefined) {
|
|
94
214
|
disconnectLazyHydration(this);
|
|
95
215
|
}
|
|
@@ -103,7 +223,8 @@ export class WebUIElement extends TemplateElement {
|
|
|
103
223
|
return attribute === undefined || !this.hasAttribute(attribute);
|
|
104
224
|
}
|
|
105
225
|
$syncAuthoredAttributes() {
|
|
106
|
-
|
|
226
|
+
if (this.isConnected)
|
|
227
|
+
syncAttrProperties(this, this.constructor);
|
|
107
228
|
}
|
|
108
229
|
$emit(name, detail) {
|
|
109
230
|
return this.dispatchEvent(new CustomEvent(name, {
|
package/dist/lifecycle.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isStreamingHydrationMode } from './streaming-mode.js';
|
|
1
2
|
let pendingCount = 0;
|
|
2
3
|
let started = false;
|
|
3
4
|
let completed = false;
|
|
@@ -74,6 +75,9 @@ function tryComplete() {
|
|
|
74
75
|
streamingGateAborted ||
|
|
75
76
|
pendingCount !== 0)
|
|
76
77
|
return;
|
|
78
|
+
if (!streamingGateActive && hasBrowserDocument && isStreamingHydrationMode()) {
|
|
79
|
+
streamingGateActive = true;
|
|
80
|
+
}
|
|
77
81
|
if (!started && !streamingGateActive)
|
|
78
82
|
return;
|
|
79
83
|
if (streamingGateActive &&
|
package/dist/static-host.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { consumePendingParentState, TemplateElement, } from './template-element.js';
|
|
2
2
|
import { hasComponentStyleWork } from './element/styles.js';
|
|
3
|
-
import { getTemplateRegistry } from './template.js';
|
|
3
|
+
import { getTemplateRegistry, installTemplateDefinitionPreparation, } from './template.js';
|
|
4
4
|
import { templateNeedsStaticHost } from './template-roots.js';
|
|
5
5
|
import { ACTIVATION_STATIC_HOST_OPT_OUT, isStreamingHydrationMode, STREAMED_HOST_ATTR, STREAMING_BOUNDARY_ACTIVATE, } from './streaming-mode.js';
|
|
6
6
|
import { TEMPLATES_REGISTERED_EVENT, templateRegistrationDetail, } from './template-events.js';
|
|
@@ -97,6 +97,7 @@ export function installTemplateElementRuntime() {
|
|
|
97
97
|
if (typeof window === 'undefined' || typeof document === 'undefined')
|
|
98
98
|
return;
|
|
99
99
|
runtimeInstalled = true;
|
|
100
|
+
installTemplateDefinitionPreparation(null);
|
|
100
101
|
window.addEventListener(TEMPLATES_REGISTERED_EVENT, (event) => {
|
|
101
102
|
const detail = templateRegistrationDetail(event);
|
|
102
103
|
if (!detail?.templates)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { registerTemplateData } from './template.js';
|
|
2
|
-
import { registerComponentStyles } from './element/
|
|
1
|
+
import { registerTemplateData } from './template-registry.js';
|
|
2
|
+
import { registerComponentStyles } from './element/style-catalog.js';
|
|
3
3
|
export function applyBoundaryBootstrap(bootstrap) {
|
|
4
4
|
registerComponentStyles(bootstrap.componentStyles);
|
|
5
5
|
if (bootstrap.templates)
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { markLateActivationPending, settleLateActivation, } from './lifecycle.js';
|
|
2
2
|
import { abandonDeferredDescendants, abandonDeferredElement, removeStreamingAttributes, } from './streaming-cleanup.js';
|
|
3
3
|
import { firstNodeWithin, MAX_ELEMENTS_PER_BOUNDARY, MAX_MARKER_SCAN_NODES, nextAfterSubtreeWithin, nextWithinRoot, STREAMING_ENCLOSING_SPAN_ATTR, streamingErrorMessage, } from './streaming-dom.js';
|
|
4
|
-
import { ACTIVATION_ACTIVATED, ACTIVATION_ANCESTOR_BARRIER, ACTIVATION_MISSING_TEMPLATE, ACTIVATION_STATIC_HOST_OPT_OUT,
|
|
4
|
+
import { ACTIVATION_ACTIVATED, ACTIVATION_ANCESTOR_BARRIER, ACTIVATION_MISSING_TEMPLATE, ACTIVATION_STATIC_HOST_OPT_OUT, registerStreamingRootResume, STREAMED_HOST_ATTR, STREAMING_BOUNDARY_ACTIVATE, } from './streaming-mode.js';
|
|
5
5
|
import { applyStateUpdate } from './streaming-state.js';
|
|
6
|
+
import { templateNeedsStaticHost } from './template-roots.js';
|
|
7
|
+
import { invalidateTemplateHostRuntime, loadTemplateHostRuntime, resetTemplateHostRuntimeForTests, } from './streaming-template-hosts.js';
|
|
6
8
|
export const ELEMENT_IGNORED = 10;
|
|
7
9
|
export const ELEMENT_DEFERRED = 11;
|
|
8
10
|
export const ELEMENT_LIMIT_FAILURE = 12;
|
|
@@ -20,9 +22,11 @@ const pendingTagWaiters = new Map();
|
|
|
20
22
|
const pendingBarrierRoots = new Set();
|
|
21
23
|
let pendingUndefinedRoots = 0;
|
|
22
24
|
let activationGeneration = 0;
|
|
25
|
+
let templateHostRuntimeRequested = false;
|
|
23
26
|
let failureHandler = null;
|
|
24
27
|
let invalidActivationOutcome;
|
|
25
|
-
|
|
28
|
+
let pendingRootRecords;
|
|
29
|
+
registerStreamingRootResume(resumeRetainedElement);
|
|
26
30
|
export function configureStreamingFailureHandler(handler) {
|
|
27
31
|
failureHandler = handler;
|
|
28
32
|
}
|
|
@@ -89,23 +93,45 @@ function activateMarkedElement(el, state, updates, bypass) {
|
|
|
89
93
|
customElements
|
|
90
94
|
.whenDefined(tag)
|
|
91
95
|
.then(() => onTagDefined(tag, generation));
|
|
96
|
+
requestTemplateHostRuntime(tag, generation);
|
|
92
97
|
}
|
|
93
98
|
if (!waiter.roots.has(el)) {
|
|
94
99
|
waiter.roots.add(el);
|
|
95
100
|
pendingUndefinedRoots++;
|
|
96
101
|
}
|
|
97
|
-
el[PENDING_ROOT_CONNECTED] = resumePendingRoot;
|
|
98
102
|
return ELEMENT_DEFERRED;
|
|
99
103
|
}
|
|
104
|
+
function resumeRetainedElement(el) {
|
|
105
|
+
if (!hasPendingRecord(el))
|
|
106
|
+
return false;
|
|
107
|
+
if (pendingBarrierRoots.has(el))
|
|
108
|
+
resumeBarrierRoot.call(el);
|
|
109
|
+
else
|
|
110
|
+
resumePendingRoot.call(el);
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
function requestTemplateHostRuntime(tag, generation) {
|
|
114
|
+
if (templateHostRuntimeRequested)
|
|
115
|
+
return;
|
|
116
|
+
const meta = window.__webui?.templates?.[tag];
|
|
117
|
+
if (!meta || !templateNeedsStaticHost(meta))
|
|
118
|
+
return;
|
|
119
|
+
if (window.__webui?.templateHostExclusions?.has(tag))
|
|
120
|
+
return;
|
|
121
|
+
templateHostRuntimeRequested = true;
|
|
122
|
+
void loadTemplateHostRuntime()?.catch((error) => {
|
|
123
|
+
if (generation === activationGeneration) {
|
|
124
|
+
fail(`failed to load template-host runtime: ${streamingErrorMessage(error)}`);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
100
128
|
function deferBehindBarrier(el, state, updates, bypass) {
|
|
101
129
|
stashPendingRecord(el, state, updates, bypass);
|
|
102
130
|
pendingBarrierRoots.add(el);
|
|
103
|
-
el[PENDING_ROOT_CONNECTED] = resumeBarrierRoot;
|
|
104
131
|
}
|
|
105
132
|
function activatePendingBarrierRoot(el) {
|
|
106
133
|
if (!pendingBarrierRoots.delete(el))
|
|
107
134
|
return ELEMENT_IGNORED;
|
|
108
|
-
delete el[PENDING_ROOT_CONNECTED];
|
|
109
135
|
const record = takePendingRecord(el);
|
|
110
136
|
const updates = releaseUpdates(record);
|
|
111
137
|
try {
|
|
@@ -180,7 +206,6 @@ function resumePendingRoot() {
|
|
|
180
206
|
if (!waiter ||
|
|
181
207
|
waiter.generation !== activationGeneration ||
|
|
182
208
|
!waiter.roots.has(this)) {
|
|
183
|
-
delete this[PENDING_ROOT_CONNECTED];
|
|
184
209
|
return;
|
|
185
210
|
}
|
|
186
211
|
activatePendingRoot(tag, waiter, this);
|
|
@@ -189,7 +214,6 @@ function activatePendingRoot(tag, waiter, el) {
|
|
|
189
214
|
if (!waiter.roots.delete(el))
|
|
190
215
|
return;
|
|
191
216
|
pendingUndefinedRoots--;
|
|
192
|
-
delete el[PENDING_ROOT_CONNECTED];
|
|
193
217
|
const record = takePendingRecord(el);
|
|
194
218
|
const updates = releaseUpdates(record);
|
|
195
219
|
const state = record?.state;
|
|
@@ -309,6 +333,8 @@ function abandonDeferredTree(el) {
|
|
|
309
333
|
abandonDeferredElement(el);
|
|
310
334
|
}
|
|
311
335
|
export function abandonPendingWaiters() {
|
|
336
|
+
activationGeneration++;
|
|
337
|
+
invalidateTemplateHostRuntime();
|
|
312
338
|
if (pendingBarrierRoots.size !== 0) {
|
|
313
339
|
for (const el of pendingBarrierRoots)
|
|
314
340
|
clearPendingRoot(el);
|
|
@@ -323,28 +349,30 @@ export function abandonPendingWaiters() {
|
|
|
323
349
|
pendingTagWaiters.clear();
|
|
324
350
|
}
|
|
325
351
|
pendingUndefinedRoots = 0;
|
|
352
|
+
pendingRootRecords = undefined;
|
|
326
353
|
}
|
|
327
354
|
function clearPendingRoot(el) {
|
|
328
355
|
releaseUpdates(takePendingRecord(el));
|
|
329
|
-
delete el[PENDING_ROOT_CONNECTED];
|
|
330
356
|
abandonDeferredTree(el);
|
|
331
357
|
}
|
|
332
358
|
function stashPendingRecord(el, state, updates, bypass) {
|
|
333
|
-
el
|
|
359
|
+
(pendingRootRecords ??= new WeakMap()).set(el, {
|
|
334
360
|
state,
|
|
335
361
|
updates,
|
|
336
362
|
bypass,
|
|
337
|
-
};
|
|
363
|
+
});
|
|
338
364
|
if (updates)
|
|
339
365
|
updates.pendingRoots++;
|
|
340
366
|
}
|
|
341
367
|
function hasPendingRecord(el) {
|
|
342
|
-
return
|
|
368
|
+
return pendingRootRecords?.has(el) ?? false;
|
|
343
369
|
}
|
|
344
370
|
function takePendingRecord(el) {
|
|
345
|
-
const
|
|
346
|
-
|
|
347
|
-
|
|
371
|
+
const record = pendingRootRecords?.get(el);
|
|
372
|
+
pendingRootRecords?.delete(el);
|
|
373
|
+
if (pendingUndefinedRoots === 0 && pendingBarrierRoots.size === 0) {
|
|
374
|
+
pendingRootRecords = undefined;
|
|
375
|
+
}
|
|
348
376
|
return record;
|
|
349
377
|
}
|
|
350
378
|
function releaseUpdates(record) {
|
|
@@ -384,7 +412,8 @@ function invokeActivationHook(el, state, bypass) {
|
|
|
384
412
|
}
|
|
385
413
|
export function resetDeferredActivationForTests() {
|
|
386
414
|
abandonPendingWaiters();
|
|
387
|
-
|
|
415
|
+
templateHostRuntimeRequested = false;
|
|
416
|
+
resetTemplateHostRuntimeForTests();
|
|
388
417
|
}
|
|
389
418
|
export function pendingTagWaiterCountForTests() {
|
|
390
419
|
return pendingTagWaiters.size;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { beginStreamingGate } from './lifecycle.js';
|
|
2
|
-
import { installTemplateElementRuntime } from './static-host.js';
|
|
3
2
|
import { enqueueStreamingSentinel, installStreamingTruncationGuard, } from './streaming-coordinator.js';
|
|
4
3
|
import { isStreamingHydrationMode } from './streaming-mode.js';
|
|
4
|
+
import { installTemplateDefinitionPreparation } from './template-registry.js';
|
|
5
|
+
import { prepareTemplateDefinitions } from './streaming-template-hosts.js';
|
|
5
6
|
const SENTINEL_TAG = 'webui-hydrate';
|
|
6
7
|
let installed = false;
|
|
7
8
|
class WebUiHydrateSentinel extends HTMLElement {
|
|
@@ -13,12 +14,12 @@ export function installStreamingCoordinator() {
|
|
|
13
14
|
if (installed || !isStreamingHydrationMode())
|
|
14
15
|
return;
|
|
15
16
|
installed = true;
|
|
17
|
+
installTemplateDefinitionPreparation(prepareTemplateDefinitions);
|
|
16
18
|
if (!customElements.get(SENTINEL_TAG)) {
|
|
17
19
|
customElements.define(SENTINEL_TAG, WebUiHydrateSentinel);
|
|
18
20
|
}
|
|
19
21
|
beginStreamingGate();
|
|
20
22
|
installStreamingTruncationGuard();
|
|
21
|
-
installTemplateElementRuntime();
|
|
22
23
|
}
|
|
23
24
|
export function resetStreamingInstallForTests() {
|
|
24
25
|
installed = false;
|
package/dist/streaming-mode.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export declare const STREAMING_BOUNDARY_ACTIVATE: unique symbol;
|
|
2
|
-
export declare
|
|
2
|
+
export declare let resumeStreamingRoot: ((element: Element) => boolean) | undefined;
|
|
3
|
+
export declare function registerStreamingRootResume(resume: typeof resumeStreamingRoot): void;
|
|
3
4
|
export declare const STREAMED_HOST_ATTR = "data-ws";
|
|
4
5
|
export declare const ACTIVATION_ACTIVATED = 1;
|
|
5
6
|
export declare const ACTIVATION_STATIC_HOST_OPT_OUT = 2;
|
package/dist/streaming-mode.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
let cached;
|
|
2
2
|
export const STREAMING_BOUNDARY_ACTIVATE = Symbol.for('microsoft.webui.boundaryActivate');
|
|
3
|
-
export
|
|
3
|
+
export let resumeStreamingRoot;
|
|
4
|
+
export function registerStreamingRootResume(resume) {
|
|
5
|
+
resumeStreamingRoot = resume;
|
|
6
|
+
}
|
|
4
7
|
export const STREAMED_HOST_ATTR = 'data-ws';
|
|
5
8
|
export const ACTIVATION_ACTIVATED = 1;
|
|
6
9
|
export const ACTIVATION_STATIC_HOST_OPT_OUT = 2;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { TemplateMeta } from './template-types.js';
|
|
2
|
+
export declare function loadTemplateHostRuntime(): Promise<void> | undefined;
|
|
3
|
+
export declare function prepareTemplateDefinitions(templates: Record<string, TemplateMeta>, names: readonly string[]): Promise<void> | undefined;
|
|
4
|
+
export declare function invalidateTemplateHostRuntime(): void;
|
|
5
|
+
export declare function resetTemplateHostRuntimeForTests(): void;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { templateNeedsStaticHost } from './template-roots.js';
|
|
2
|
+
let generation = 0;
|
|
3
|
+
let installed = false;
|
|
4
|
+
let pending;
|
|
5
|
+
export function loadTemplateHostRuntime() {
|
|
6
|
+
if (installed)
|
|
7
|
+
return;
|
|
8
|
+
if (!pending) {
|
|
9
|
+
const current = generation;
|
|
10
|
+
pending = import('./static-host.js').then(({ installTemplateElementRuntime }) => {
|
|
11
|
+
if (current !== generation) {
|
|
12
|
+
throw new Error('[WebUI] Template-host activation was abandoned.');
|
|
13
|
+
}
|
|
14
|
+
installTemplateElementRuntime();
|
|
15
|
+
installed = true;
|
|
16
|
+
pending = undefined;
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
return pending;
|
|
20
|
+
}
|
|
21
|
+
export function prepareTemplateDefinitions(templates, names) {
|
|
22
|
+
const exclusions = window.__webui?.templateHostExclusions;
|
|
23
|
+
for (let i = 0; i < names.length; i++) {
|
|
24
|
+
const tag = names[i];
|
|
25
|
+
if (templateNeedsStaticHost(templates[tag]) &&
|
|
26
|
+
!exclusions?.has(tag) &&
|
|
27
|
+
!customElements.get(tag)) {
|
|
28
|
+
return loadTemplateHostRuntime();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function invalidateTemplateHostRuntime() {
|
|
33
|
+
generation++;
|
|
34
|
+
pending = undefined;
|
|
35
|
+
}
|
|
36
|
+
export function resetTemplateHostRuntimeForTests() {
|
|
37
|
+
invalidateTemplateHostRuntime();
|
|
38
|
+
installed = false;
|
|
39
|
+
}
|
|
@@ -13,5 +13,6 @@ export interface TemplateStylesheetDescriptor {
|
|
|
13
13
|
readonly type: string;
|
|
14
14
|
}
|
|
15
15
|
export declare function cloneTemplateContent(meta: TemplateBlockMeta): DocumentFragment;
|
|
16
|
+
export declare function getTemplateFragment(meta: TemplateBlockMeta): DocumentFragment;
|
|
16
17
|
export declare function getTemplateStylesheets(meta: TemplateBlockMeta): readonly TemplateStylesheetDescriptor[] | undefined;
|
|
17
18
|
export declare function templateHtmlMayContainLink(html: string): boolean;
|
package/dist/template-content.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
import { setTemplateContent } from './trusted-types-policy.js';
|
|
1
2
|
const EMPTY_STYLESHEETS = Object.freeze([]);
|
|
2
3
|
const NO_LINK_STYLESHEETS = Object.freeze([]);
|
|
3
4
|
const templateContentCache = new WeakMap();
|
|
4
5
|
export function cloneTemplateContent(meta) {
|
|
5
|
-
return
|
|
6
|
+
return getTemplateFragment(meta).cloneNode(true);
|
|
7
|
+
}
|
|
8
|
+
export function getTemplateFragment(meta) {
|
|
9
|
+
return getTemplateContent(meta).fragment;
|
|
6
10
|
}
|
|
7
11
|
export function getTemplateStylesheets(meta) {
|
|
8
12
|
const stylesheets = getTemplateContent(meta, true).stylesheets;
|
|
@@ -37,7 +41,7 @@ function getTemplateContent(meta, mayContainLink) {
|
|
|
37
41
|
if (cached)
|
|
38
42
|
return cached;
|
|
39
43
|
const template = document.createElement('template');
|
|
40
|
-
template
|
|
44
|
+
setTemplateContent(template, meta);
|
|
41
45
|
const fragment = template.content;
|
|
42
46
|
const stylesheets = (mayContainLink ?? templateHtmlMayContainLink(meta.h))
|
|
43
47
|
? collectStylesheetDescriptors(fragment)
|
|
@@ -19,7 +19,7 @@ export declare class TemplateElement extends HTMLElement {
|
|
|
19
19
|
private $hydrated;
|
|
20
20
|
private $deferredClientMount;
|
|
21
21
|
private $resetClientShadow;
|
|
22
|
-
private $
|
|
22
|
+
private $mountPhase;
|
|
23
23
|
private $deferredSSR;
|
|
24
24
|
private $activatingDeferredSSR;
|
|
25
25
|
private $deferredAncestor;
|
|
@@ -78,7 +78,7 @@ export declare class TemplateElement extends HTMLElement {
|
|
|
78
78
|
protected $shouldApplySSRState(_key: string): boolean;
|
|
79
79
|
protected $syncAuthoredAttributes(): void;
|
|
80
80
|
protected hydratedCallback(): void;
|
|
81
|
-
|
|
81
|
+
protected $notifyHydrated(): void;
|
|
82
82
|
private $finishHydration;
|
|
83
83
|
protected $shouldApplyTemplateStateFromSSR(_key: string): boolean;
|
|
84
84
|
protected $setTemplateState(key: string, value: unknown): boolean;
|
|
@@ -93,6 +93,8 @@ export declare class TemplateElement extends HTMLElement {
|
|
|
93
93
|
private $recordDeferredWrite;
|
|
94
94
|
private $replayDeferredWrites;
|
|
95
95
|
$flushUpdates(): void;
|
|
96
|
+
protected $reconcileAuthoredState(): boolean;
|
|
97
|
+
protected $canRunAuthoredEffects(): boolean;
|
|
96
98
|
private $flush;
|
|
97
99
|
private $recordPreReadyWrite;
|
|
98
100
|
private $checkHydrationMismatch;
|