@wcstack/state 4.1.1 → 4.2.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.
- package/README.ja.md +20 -17
- package/README.md +20 -17
- package/dist/auto.min.js +1 -1
- package/dist/auto.min.js.map +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/manifest.esm.js +73 -34
- package/dist/parser.esm.js +10 -4
- package/dist/split/auto.js +1 -1
- package/dist/split/chunks/chunk-2RBI6DVS.js +2 -0
- package/dist/split/chunks/chunk-2RBI6DVS.js.map +1 -0
- package/dist/split/chunks/{chunk-V3HFN3MW.js → chunk-3Q7LGONS.js} +2 -2
- package/dist/split/chunks/{chunk-V3HFN3MW.js.map → chunk-3Q7LGONS.js.map} +1 -1
- package/dist/split/chunks/{chunk-UFIDBJBP.js → chunk-4ECL4ITF.js} +2 -2
- package/dist/split/chunks/{chunk-7ZU3CLEG.js → chunk-BGUJ3HF6.js} +2 -2
- package/dist/split/chunks/{chunk-4HLDITUB.js → chunk-BI4645UG.js} +2 -2
- package/dist/split/chunks/chunk-BI4645UG.js.map +1 -0
- package/dist/split/chunks/{chunk-JAEYZSVS.js → chunk-BYQBV3ZC.js} +2 -2
- package/dist/split/chunks/{chunk-R5OJ52SF.js → chunk-CIBJLAA3.js} +2 -2
- package/dist/split/chunks/{chunk-R5OJ52SF.js.map → chunk-CIBJLAA3.js.map} +1 -1
- package/dist/split/chunks/chunk-JK3B3LLB.js +2 -0
- package/dist/split/chunks/chunk-OKBVNGFK.js +2 -0
- package/dist/split/chunks/{chunk-JZW5KGXQ.js.map → chunk-OKBVNGFK.js.map} +1 -1
- package/dist/split/chunks/{chunk-GGSHXG7N.js → chunk-UBGJGMSG.js} +2 -2
- package/dist/split/chunks/chunk-UBGJGMSG.js.map +1 -0
- package/dist/split/chunks/{chunk-7QVEF5E3.js → chunk-UPSLR4FS.js} +2 -2
- package/dist/split/core.js +1 -1
- package/dist/split/features/devtools.js +1 -1
- package/dist/split/features/diagnostics.js +1 -1
- package/dist/split/features/diagnostics.js.map +1 -1
- package/dist/split/features/formats.d.ts +1 -1
- package/dist/split/features/formats.js +1 -1
- package/dist/split/features/formats.js.map +1 -1
- package/dist/split/features/list-keys.js +1 -1
- package/dist/split/features/native-commands.js +1 -1
- package/dist/split/features/recursion.js +1 -1
- package/dist/split/features/scopes.js +1 -1
- package/dist/split/features/ssr.js +1 -1
- package/dist/split/features/temporal.js +1 -1
- package/dist/split/features/temporal.js.map +1 -1
- package/dist/wcs-manifest.json +25 -7
- package/package.json +1 -1
- package/dist/split/chunks/chunk-4HLDITUB.js.map +0 -1
- package/dist/split/chunks/chunk-BWGPKDHS.js +0 -2
- package/dist/split/chunks/chunk-BWGPKDHS.js.map +0 -1
- package/dist/split/chunks/chunk-GGSHXG7N.js.map +0 -1
- package/dist/split/chunks/chunk-JZW5KGXQ.js +0 -2
- package/dist/split/chunks/chunk-XEGL4FW5.js +0 -2
- /package/dist/split/chunks/{chunk-UFIDBJBP.js.map → chunk-4ECL4ITF.js.map} +0 -0
- /package/dist/split/chunks/{chunk-7ZU3CLEG.js.map → chunk-BGUJ3HF6.js.map} +0 -0
- /package/dist/split/chunks/{chunk-JAEYZSVS.js.map → chunk-BYQBV3ZC.js.map} +0 -0
- /package/dist/split/chunks/{chunk-XEGL4FW5.js.map → chunk-JK3B3LLB.js.map} +0 -0
- /package/dist/split/chunks/{chunk-7QVEF5E3.js.map → chunk-UPSLR4FS.js.map} +0 -0
package/dist/manifest.esm.js
CHANGED
|
@@ -51,11 +51,17 @@ function optionsRequired(fnName) {
|
|
|
51
51
|
function optionMustBeNumber(fnName) {
|
|
52
52
|
raise(27 /* FilterOptionNotNumber */, [fnName]);
|
|
53
53
|
}
|
|
54
|
-
function
|
|
55
|
-
raise(
|
|
54
|
+
function styleInvalid(fnName, value) {
|
|
55
|
+
raise(52 /* FilterStyleInvalid */, [fnName, value]);
|
|
56
56
|
}
|
|
57
|
-
function
|
|
58
|
-
raise(
|
|
57
|
+
function currencyInvalid(value) {
|
|
58
|
+
raise(53 /* FilterCurrencyInvalid */, [value]);
|
|
59
|
+
}
|
|
60
|
+
function valueMustBeNumber(fnName, value) {
|
|
61
|
+
raise(28 /* FilterValueNotNumber */, [fnName, value]);
|
|
62
|
+
}
|
|
63
|
+
function valueMustBeDate(fnName, value) {
|
|
64
|
+
raise(29 /* FilterValueNotDate */, [fnName, value]);
|
|
59
65
|
}
|
|
60
66
|
function valueMustBeArray(fnName) {
|
|
61
67
|
raise(30 /* FilterValueNotArray */, [fnName]);
|
|
@@ -126,7 +132,7 @@ var numeric = (name, op) => ({
|
|
|
126
132
|
const opt = requiredNumberOption(options, 0, name);
|
|
127
133
|
return (value) => {
|
|
128
134
|
if (typeof value !== "number") {
|
|
129
|
-
valueMustBeNumber(name);
|
|
135
|
+
valueMustBeNumber(name, value);
|
|
130
136
|
}
|
|
131
137
|
return op(value, opt);
|
|
132
138
|
};
|
|
@@ -158,7 +164,7 @@ var toFixed = (options) => {
|
|
|
158
164
|
const opt = numberOption(options?.[0] ?? "0", "toFixed");
|
|
159
165
|
return (value) => {
|
|
160
166
|
if (typeof value !== "number") {
|
|
161
|
-
valueMustBeNumber("toFixed");
|
|
167
|
+
valueMustBeNumber("toFixed", value);
|
|
162
168
|
}
|
|
163
169
|
return value.toFixed(opt);
|
|
164
170
|
};
|
|
@@ -167,7 +173,7 @@ var round = (options) => {
|
|
|
167
173
|
const optValue = Math.pow(10, numberOption(options?.[0] ?? "0", "round"));
|
|
168
174
|
return (value) => {
|
|
169
175
|
if (typeof value !== "number") {
|
|
170
|
-
valueMustBeNumber("round");
|
|
176
|
+
valueMustBeNumber("round", value);
|
|
171
177
|
}
|
|
172
178
|
return Math.round(value * optValue) / optValue;
|
|
173
179
|
};
|
|
@@ -176,7 +182,7 @@ var floor = (options) => {
|
|
|
176
182
|
const optValue = Math.pow(10, numberOption(options?.[0] ?? "0", "floor"));
|
|
177
183
|
return (value) => {
|
|
178
184
|
if (typeof value !== "number") {
|
|
179
|
-
valueMustBeNumber("floor");
|
|
185
|
+
valueMustBeNumber("floor", value);
|
|
180
186
|
}
|
|
181
187
|
return Math.floor(value * optValue) / optValue;
|
|
182
188
|
};
|
|
@@ -185,7 +191,7 @@ var ceil = (options) => {
|
|
|
185
191
|
const optValue = Math.pow(10, numberOption(options?.[0] ?? "0", "ceil"));
|
|
186
192
|
return (value) => {
|
|
187
193
|
if (typeof value !== "number") {
|
|
188
|
-
valueMustBeNumber("ceil");
|
|
194
|
+
valueMustBeNumber("ceil", value);
|
|
189
195
|
}
|
|
190
196
|
return Math.ceil(value * optValue) / optValue;
|
|
191
197
|
};
|
|
@@ -194,7 +200,7 @@ var percent = (options) => {
|
|
|
194
200
|
const opt = numberOption(options?.[0] ?? "0", "percent");
|
|
195
201
|
return (value) => {
|
|
196
202
|
if (typeof value !== "number") {
|
|
197
|
-
valueMustBeNumber("percent");
|
|
203
|
+
valueMustBeNumber("percent", value);
|
|
198
204
|
}
|
|
199
205
|
return `${(value * 100).toFixed(opt)}%`;
|
|
200
206
|
};
|
|
@@ -221,11 +227,29 @@ var locale = (options) => {
|
|
|
221
227
|
const explicit = options?.[0];
|
|
222
228
|
return (value) => {
|
|
223
229
|
if (typeof value !== "number") {
|
|
224
|
-
valueMustBeNumber("locale");
|
|
230
|
+
valueMustBeNumber("locale", value);
|
|
225
231
|
}
|
|
226
232
|
return value.toLocaleString(explicit ?? defaultLocale());
|
|
227
233
|
};
|
|
228
234
|
};
|
|
235
|
+
var currency = (options) => {
|
|
236
|
+
const code = options?.[0] ?? optionsRequired("currency");
|
|
237
|
+
const explicit = options?.[1];
|
|
238
|
+
const format = { style: "currency", currency: code };
|
|
239
|
+
try {
|
|
240
|
+
new Intl.NumberFormat("en", format);
|
|
241
|
+
const known = Intl.supportedValuesOf?.("currency");
|
|
242
|
+
if (known && !known.includes(code.toUpperCase())) throw 0;
|
|
243
|
+
} catch {
|
|
244
|
+
currencyInvalid(code);
|
|
245
|
+
}
|
|
246
|
+
return (value) => {
|
|
247
|
+
if (typeof value !== "number") {
|
|
248
|
+
valueMustBeNumber("currency", value);
|
|
249
|
+
}
|
|
250
|
+
return value.toLocaleString(explicit ?? defaultLocale(), format);
|
|
251
|
+
};
|
|
252
|
+
};
|
|
229
253
|
var upper = () => (value) => String(value).toUpperCase();
|
|
230
254
|
var lower = () => (value) => String(value).toLowerCase();
|
|
231
255
|
var capitalize = () => (value) => {
|
|
@@ -282,38 +306,48 @@ var join = (options) => {
|
|
|
282
306
|
return value.join(opt);
|
|
283
307
|
};
|
|
284
308
|
};
|
|
309
|
+
var STYLES = ["full", "long", "medium", "short"];
|
|
310
|
+
function dateOptions(options, fn) {
|
|
311
|
+
let [loc, style] = options ?? [];
|
|
312
|
+
if (style === void 0 && loc !== void 0 && STYLES.includes(loc)) [loc, style] = [void 0, loc];
|
|
313
|
+
if (style !== void 0 && !STYLES.includes(style)) styleInvalid(fn, style);
|
|
314
|
+
return [loc, style];
|
|
315
|
+
}
|
|
285
316
|
var date = (options) => {
|
|
286
|
-
const explicit = options
|
|
317
|
+
const [explicit, style] = dateOptions(options, "date");
|
|
318
|
+
const format = style && { dateStyle: style };
|
|
287
319
|
return (value) => {
|
|
288
320
|
if (!(value instanceof Date)) {
|
|
289
|
-
valueMustBeDate("date");
|
|
321
|
+
valueMustBeDate("date", value);
|
|
290
322
|
}
|
|
291
|
-
return value.toLocaleDateString(explicit ?? defaultLocale());
|
|
323
|
+
return value.toLocaleDateString(explicit ?? defaultLocale(), format);
|
|
292
324
|
};
|
|
293
325
|
};
|
|
294
326
|
var time = (options) => {
|
|
295
|
-
const explicit = options
|
|
327
|
+
const [explicit, style] = dateOptions(options, "time");
|
|
328
|
+
const format = style && { timeStyle: style };
|
|
296
329
|
return (value) => {
|
|
297
330
|
if (!(value instanceof Date)) {
|
|
298
|
-
valueMustBeDate("time");
|
|
331
|
+
valueMustBeDate("time", value);
|
|
299
332
|
}
|
|
300
|
-
return value.toLocaleTimeString(explicit ?? defaultLocale());
|
|
333
|
+
return value.toLocaleTimeString(explicit ?? defaultLocale(), format);
|
|
301
334
|
};
|
|
302
335
|
};
|
|
303
336
|
var datetime = (options) => {
|
|
304
|
-
const explicit = options
|
|
337
|
+
const [explicit, style] = dateOptions(options, "datetime");
|
|
338
|
+
const format = style && { dateStyle: style, timeStyle: style };
|
|
305
339
|
return (value) => {
|
|
306
340
|
if (!(value instanceof Date)) {
|
|
307
|
-
valueMustBeDate("datetime");
|
|
341
|
+
valueMustBeDate("datetime", value);
|
|
308
342
|
}
|
|
309
|
-
return value.toLocaleString(explicit ?? defaultLocale());
|
|
343
|
+
return value.toLocaleString(explicit ?? defaultLocale(), format);
|
|
310
344
|
};
|
|
311
345
|
};
|
|
312
346
|
var ymd = (options) => {
|
|
313
347
|
const opt = options?.[0] ?? "-";
|
|
314
348
|
return (value) => {
|
|
315
349
|
if (!(value instanceof Date)) {
|
|
316
|
-
valueMustBeDate("ymd");
|
|
350
|
+
valueMustBeDate("ymd", value);
|
|
317
351
|
}
|
|
318
352
|
const year = value.getFullYear().toString();
|
|
319
353
|
const month = (value.getMonth() + 1).toString().padStart(2, "0");
|
|
@@ -325,7 +359,7 @@ var hms = (options) => {
|
|
|
325
359
|
const opt = options?.[0] ?? ":";
|
|
326
360
|
return (value) => {
|
|
327
361
|
if (!(value instanceof Date)) {
|
|
328
|
-
valueMustBeDate("hms");
|
|
362
|
+
valueMustBeDate("hms", value);
|
|
329
363
|
}
|
|
330
364
|
const hours = value.getHours().toString().padStart(2, "0");
|
|
331
365
|
const minutes = value.getMinutes().toString().padStart(2, "0");
|
|
@@ -335,7 +369,7 @@ var hms = (options) => {
|
|
|
335
369
|
};
|
|
336
370
|
var abs = () => (value) => {
|
|
337
371
|
if (typeof value !== "number") {
|
|
338
|
-
valueMustBeNumber("abs");
|
|
372
|
+
valueMustBeNumber("abs", value);
|
|
339
373
|
}
|
|
340
374
|
return Math.abs(value);
|
|
341
375
|
};
|
|
@@ -344,7 +378,7 @@ var clamp = (options) => {
|
|
|
344
378
|
const max = requiredNumberOption(options, 1, "clamp");
|
|
345
379
|
return (value) => {
|
|
346
380
|
if (typeof value !== "number") {
|
|
347
|
-
valueMustBeNumber("clamp");
|
|
381
|
+
valueMustBeNumber("clamp", value);
|
|
348
382
|
}
|
|
349
383
|
return Math.min(Math.max(value, min), max);
|
|
350
384
|
};
|
|
@@ -391,10 +425,10 @@ var registered = {
|
|
|
391
425
|
ceil: { factory: ceil, arity: [0, 1] },
|
|
392
426
|
percent: { factory: percent, arity: [0, 1] },
|
|
393
427
|
unit: { factory: nullishPassthrough(unit), arity: [1, 1] },
|
|
394
|
-
// The locale-dependent three take a locale like `locale` does (`date(ja-JP)`)
|
|
395
|
-
date: { factory: date, arity: [0,
|
|
396
|
-
time: { factory: time, arity: [0,
|
|
397
|
-
datetime: { factory: datetime, arity: [0,
|
|
428
|
+
// The locale-dependent three take a locale like `locale` does (`date(ja-JP)`), and a style (`date(ja-JP,long)`)
|
|
429
|
+
date: { factory: date, arity: [0, 2] },
|
|
430
|
+
time: { factory: time, arity: [0, 2] },
|
|
431
|
+
datetime: { factory: datetime, arity: [0, 2] },
|
|
398
432
|
ymd: { factory: ymd, arity: [0, 1] },
|
|
399
433
|
hms: { factory: hms, arity: [0, 1] },
|
|
400
434
|
// the core set of 4.0.0-rc.3 (the core's own: eq ne not lt le gt ge falsy truthy boolean)
|
|
@@ -421,7 +455,9 @@ var registered = {
|
|
|
421
455
|
boolean: boolean2,
|
|
422
456
|
number: { factory: number, arity: [0, 0] },
|
|
423
457
|
string: { factory: string, arity: [0, 0] },
|
|
424
|
-
nullIfEmpty: { factory: nullIfEmpty, arity: [0, 0] }
|
|
458
|
+
nullIfEmpty: { factory: nullIfEmpty, arity: [0, 0] },
|
|
459
|
+
// (added in 4.2: last, so the order of the others is unchanged)
|
|
460
|
+
currency: { factory: currency, arity: [1, 2] }
|
|
425
461
|
};
|
|
426
462
|
var formatFilters = /* @__PURE__ */ Object.fromEntries(
|
|
427
463
|
/* @__PURE__ */ Object.entries(registered).filter(([name]) => !(name in coreFilters))
|
|
@@ -498,10 +534,11 @@ var builtinFilterMeta = {
|
|
|
498
534
|
unit: { description: "\u5358\u4F4D\uFF08\u63A5\u5C3E\u8F9E\uFF09\u3092\u4ED8\u52A0", hasArgs: true, resultType: "string", acceptTypes: ["number", "string"], minArgs: 1, maxArgs: 1, argTypes: ["string"] },
|
|
499
535
|
// 日付・時刻
|
|
500
536
|
// `locale` と同じくロケールを 1 つ受ける(`date(ja-JP)`)。実装は最初からこれを読んでいたが、
|
|
501
|
-
// メタデータ側が maxArgs: 0 だったため lint
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
537
|
+
// メタデータ側が maxArgs: 0 だったため lint と補完が正しい書き方を誤りとして報告していた。
|
|
538
|
+
// 4.2: 2 つ目は書式(full / long / medium / short — Intl の dateStyle / timeStyle)。書式だけなら既定のロケール
|
|
539
|
+
date: { description: "\u30ED\u30B1\u30FC\u30EB\u5F62\u5F0F\u306E\u65E5\u4ED8 ([locale][, style]\u3002style \u306F full / long / medium / short\u3001\u65E2\u5B9A\u306E\u30ED\u30B1\u30FC\u30EB\u306F config.locale)", hasArgs: true, resultType: "string", acceptTypes: "any", minArgs: 0, maxArgs: 2, argTypes: ["string", "string"] },
|
|
540
|
+
time: { description: "\u30ED\u30B1\u30FC\u30EB\u5F62\u5F0F\u306E\u6642\u523B ([locale][, style]\u3002style \u306F full / long / medium / short\u3001\u65E2\u5B9A\u306E\u30ED\u30B1\u30FC\u30EB\u306F config.locale)", hasArgs: true, resultType: "string", acceptTypes: "any", minArgs: 0, maxArgs: 2, argTypes: ["string", "string"] },
|
|
541
|
+
datetime: { description: "\u30ED\u30B1\u30FC\u30EB\u5F62\u5F0F\u306E\u65E5\u6642 ([locale][, style]\u3002style \u306F full / long / medium / short\u3001\u65E2\u5B9A\u306E\u30ED\u30B1\u30FC\u30EB\u306F config.locale)", hasArgs: true, resultType: "string", acceptTypes: "any", minArgs: 0, maxArgs: 2, argTypes: ["string", "string"] },
|
|
505
542
|
ymd: { description: "YYYY-MM-DD \u5F62\u5F0F ([separator]\u3002\u65E2\u5B9A\u306F -)", hasArgs: true, resultType: "string", acceptTypes: "any", minArgs: 0, maxArgs: 1, argTypes: ["string"] },
|
|
506
543
|
hms: { description: "HH:MM:SS \u5F62\u5F0F ([separator]\u3002\u65E2\u5B9A\u306F :)", hasArgs: true, resultType: "string", acceptTypes: "any", minArgs: 0, maxArgs: 1, argTypes: ["string"] },
|
|
507
544
|
// 真偽値・変換
|
|
@@ -512,7 +549,9 @@ var builtinFilterMeta = {
|
|
|
512
549
|
boolean: { description: "\u30D6\u30FC\u30EB\u5024\u306B\u5909\u63DB", hasArgs: false, resultType: "boolean", acceptTypes: "any", minArgs: 0, maxArgs: 0 },
|
|
513
550
|
number: { description: "\u6570\u5024\u306B\u5909\u63DB", hasArgs: false, resultType: "number", acceptTypes: "any", minArgs: 0, maxArgs: 0 },
|
|
514
551
|
string: { description: "\u6587\u5B57\u5217\u306B\u5909\u63DB", hasArgs: false, resultType: "string", acceptTypes: "any", minArgs: 0, maxArgs: 0 },
|
|
515
|
-
nullIfEmpty: { description: "\u7A7A\u6587\u5B57\u5217\u3092null\u306B\u5909\u63DB", hasArgs: false, resultType: "passthrough", acceptTypes: ["string"], minArgs: 0, maxArgs: 0 }
|
|
552
|
+
nullIfEmpty: { description: "\u7A7A\u6587\u5B57\u5217\u3092null\u306B\u5909\u63DB", hasArgs: false, resultType: "passthrough", acceptTypes: ["string"], minArgs: 0, maxArgs: 0 },
|
|
553
|
+
// 4.2(formats の最後に登録)
|
|
554
|
+
currency: { description: "\u901A\u8CA8\u306E\u66F8\u5F0F (code[, locale]\u3002code \u306F ISO 4217 \u2014 JPY / USD / EUR\u3001\u65E2\u5B9A\u306E\u30ED\u30B1\u30FC\u30EB\u306F config.locale)", hasArgs: true, resultType: "string", acceptTypes: ["number"], minArgs: 1, maxArgs: 2, argTypes: ["string", "string"] }
|
|
516
555
|
};
|
|
517
556
|
|
|
518
557
|
// src/public/manifest.ts
|
package/dist/parser.esm.js
CHANGED
|
@@ -92,7 +92,8 @@ var FORMATS_FILTER_NAMES = [
|
|
|
92
92
|
"coalesce",
|
|
93
93
|
"number",
|
|
94
94
|
"string",
|
|
95
|
-
"nullIfEmpty"
|
|
95
|
+
"nullIfEmpty",
|
|
96
|
+
"currency"
|
|
96
97
|
];
|
|
97
98
|
var definitions = /* @__PURE__ */ new Map();
|
|
98
99
|
function hasFilter(name) {
|
|
@@ -325,6 +326,8 @@ var codeOf = (id) => {
|
|
|
325
326
|
return c ? `[wcs/${c}] ` : "";
|
|
326
327
|
};
|
|
327
328
|
var MOVED = ["enableMustache", "sameValueGuard", "enableDirectionalInitialSync"];
|
|
329
|
+
var was = (v) => v == null ? String(v) : v instanceof Date ? "a Date" : Array.isArray(v) ? "an array" : typeof v === "string" ? `a string (${JSON.stringify(v.length > 32 ? v.slice(0, 32) + "\u2026" : v)})` : typeof v === "object" ? "an object" : `a ${typeof v} (${String(v)})`;
|
|
330
|
+
var NAMESPACES = ["", "", "class.", "attr.", "style."];
|
|
328
331
|
var element = (tag, at) => `<${tag}${at.map((a, i) => i % 2 ? `="${a}"` : ` ${a}`).join("")}>`;
|
|
329
332
|
var CSP_GUIDE = "https://github.com/wcstack/wcstack/blob/main/docs/csp.md";
|
|
330
333
|
var SENTENCES = {
|
|
@@ -340,7 +343,8 @@ var SENTENCES = {
|
|
|
340
343
|
[10 /* SetAllSpreadLength */]: (p, n) => `$setAll("${p}", \u2026, { spread: true }) needs an array of ${n} values`,
|
|
341
344
|
[11 /* DrainNotSettled */]: () => `updates did not settle after ${MAX_DRAIN_PASSES} passes`,
|
|
342
345
|
[41 /* RenderChain */]: () => `render chain depth limit exceeded (${MAX_RENDER_CHAIN} drains that rendering itself started); bindings for this batch were not applied.`,
|
|
343
|
-
|
|
346
|
+
// (named as written — `textContent: iso`, `class.active: x` — when the binding has a member; else its type)
|
|
347
|
+
[12 /* BindingFailed */]: (type, p, name, kind) => `binding "${name ? (NAMESPACES[kind] ?? "") + name : type}: ${p}" failed to apply.`,
|
|
344
348
|
[13 /* LoadFailed */]: (src, status) => `failed to load "${src}": ${status}`,
|
|
345
349
|
[14 /* ElementFailed */]: () => "this <wcs-state> failed to initialize; create a new one",
|
|
346
350
|
[15 /* NotInitialized */]: () => "state is not initialized",
|
|
@@ -358,8 +362,10 @@ var SENTENCES = {
|
|
|
358
362
|
[25 /* NamingLimit */]: (limit) => `view-transition naming-limit (${limit}) reached.`,
|
|
359
363
|
[26 /* FilterOptionsRequired */]: (fn) => `filter ${fn} requires at least one option`,
|
|
360
364
|
[27 /* FilterOptionNotNumber */]: (fn) => `filter ${fn} requires a number as option`,
|
|
361
|
-
[28 /* FilterValueNotNumber */]: (fn) => `filter ${fn} requires a number value`,
|
|
362
|
-
[29 /* FilterValueNotDate */]: (fn) => `filter ${fn} requires a date value`,
|
|
365
|
+
[28 /* FilterValueNotNumber */]: (fn, v) => `filter ${fn} requires a number value, not ${was(v)}${typeof v === "string" ? ` \u2014 put |number before |${fn}, or convert it where it is read` : ""}`,
|
|
366
|
+
[29 /* FilterValueNotDate */]: (fn, v) => `filter ${fn} requires a date value (a Date), not ${was(v)}${typeof v === "string" || typeof v === "number" ? " \u2014 make the Date where it is read: a getter returning new Date(\u2026)" : ""}`,
|
|
367
|
+
[52 /* FilterStyleInvalid */]: (fn, v) => `filter ${fn} takes a style of full, long, medium or short, not "${v}"`,
|
|
368
|
+
[53 /* FilterCurrencyInvalid */]: (v) => `filter currency takes an ISO 4217 currency code (JPY, USD, EUR), not "${v}"`,
|
|
363
369
|
[30 /* FilterValueNotArray */]: (fn) => `filter ${fn} requires an array value`,
|
|
364
370
|
[31 /* DirectionalSyncDisabled */]: () => "init=/sync= modifiers require enableDirectionalInitialSync.",
|
|
365
371
|
[33 /* ModifierUnknown */]: (key, modifier) => `Unknown binding modifier "${key}" in "${modifier}".`,
|
package/dist/split/auto.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{d as t}from"./chunks/chunk-
|
|
1
|
+
import{d as t}from"./chunks/chunk-3Q7LGONS.js";import"./chunks/chunk-BYQBV3ZC.js";import"./chunks/chunk-4ECL4ITF.js";import"./chunks/chunk-2RBI6DVS.js";import"./chunks/chunk-BI4645UG.js";import{a as n}from"./chunks/chunk-CIBJLAA3.js";import"./chunks/chunk-JK3B3LLB.js";import"./chunks/chunk-UPSLR4FS.js";import"./chunks/chunk-UBGJGMSG.js";import{a as s,g as o}from"./chunks/chunk-BGUJ3HF6.js";var e,r=["formats","diagnostics","temporal","list-keys","scopes","recursion","ssr","devtools","native-commands"],a=(e=import.meta.url,t=>Promise.all(t.map(async t=>{if(!r.includes(t))throw new Error(`[@wcstack/state] [wcs/feature-unknown] "${t}" is not an add-on (${r.join(", ")}).`);return(await(import(new URL(`./features/${t}.js`,e).href))).default})));s.bt=t=>a(t).then(o),"loading"===document.readyState&&await new Promise(t=>document.addEventListener("DOMContentLoaded",t,{once:!0}));var c=document.querySelector(`${n.tagNames.state}:not([mount]):not([bind-component])`);o(await a(c?.getAttribute("features")?.split(/\s+/).filter(Boolean)??[])),t();
|
|
2
2
|
//# sourceMappingURL=auto.js.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{e as t}from"./chunk-CIBJLAA3.js";import{b as n}from"./chunk-UBGJGMSG.js";function r(t){n(26,[t])}function e(t){n(27,[t])}function o(t,r){n(52,[t,r])}function a(t){n(53,[t])}function f(t,r){n(28,[t,r])}function u(t,r){n(29,[t,r])}function i(t){n(30,[t])}function y(t){return!(!t||isNaN(Number(t)))}function c(t,n){return y(t)||e(n),Number(t)}function s(t,n,e){return c(t?.[n]??r(e),e)}function l(t,n){return void 0!==n&&n.length>0?n[0]:t}var m=(t,n)=>({factory:r=>{let e=s(r,0,t);return r=>("number"!=typeof r&&f(t,r),n(r,e))},arity:[1,1]}),b={eq:{factory:(t,n)=>{let o=t?.[0]??r("eq"),a=l(o,n);return t=>"number"==typeof t?"string"!=typeof a?t===a:(y(o)||e("eq"),t===Number(o)):"string"==typeof t?t===o:t===a},arity:[1,1]},ne:{factory:(t,n)=>{let o=t?.[0]??r("ne"),a=l(o,n);return t=>"number"==typeof t?"string"!=typeof a?t!==a:(y(o)||e("ne"),t!==Number(o)):"string"==typeof t?t!==o:t!==a},arity:[1,1]},not:{factory:()=>t=>!t,arity:[0,0]},lt:m("lt",(t,n)=>t<n),le:m("le",(t,n)=>t<=n),gt:m("gt",(t,n)=>t>n),ge:m("ge",(t,n)=>t>=n),falsy:{factory:()=>t=>!t,arity:[0,0]},truthy:{factory:()=>t=>!!t,arity:[0,0]},boolean:{factory:()=>t=>!!t,arity:[0,0]}},g=!1;function p(){g||(g=!0,t(b))}export{r as a,o as b,a as c,f as d,u as e,i as f,c as g,s as h,l as i,m as j,b as k,p as l};
|
|
2
|
+
//# sourceMappingURL=chunk-2RBI6DVS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["optionsRequired","fnName","raise","optionMustBeNumber","styleInvalid","value","currencyInvalid","valueMustBeNumber","valueMustBeDate","valueMustBeArray","validateNumberString","isNaN","Number","numberOption","requiredNumberOption","options","index","firstLiteral","opt","literals","length","numeric","name","op","factory","arity","coreFilters","eq","literal","ne","not","lt","le","gt","ge","falsy","truthy","boolean","installed","installCoreFilters","registerFilters","u","M","R","c","v","D","m","y","a","l","x","C"],"sources":["../../../src/filters/errorMessages.ts","../../../src/filters/options.ts","../../../src/filters/core.ts"],"sourcesContent":["/**\n * filters/errorMessages.ts — the filters' error messages, ported from `@wcstack/state`\n * (`formats/errorMessages.ts`). Numbered core messages (src/messages.ts): the sentences, the same\n * as the source's, are the diagnostics add-on's.\n */\n\nimport { raise, M } from \"../messages\";\n\n/** The filter requires an option but none was given (the factory-side guard; arity usually fires first). */\nexport function optionsRequired(fnName: string): never {\n raise(M.FilterOptionsRequired, [fnName]);\n}\n\n/** A numeric option is not a number. */\nexport function optionMustBeNumber(fnName: string): never {\n raise(M.FilterOptionNotNumber, [fnName]);\n}\n\n/** A date filter's style is not one of full / long / medium / short. */\nexport function styleInvalid(fnName: string, value: string): never {\n raise(M.FilterStyleInvalid, [fnName, value]);\n}\n\n/** `currency`'s code is not a currency Intl knows. */\nexport function currencyInvalid(value: string): never {\n raise(M.FilterCurrencyInvalid, [value]);\n}\n\n/** The value given to a numeric filter is not a number (the message says what it was). */\nexport function valueMustBeNumber(fnName: string, value: unknown): never {\n raise(M.FilterValueNotNumber, [fnName, value]);\n}\n\n/** The value given to a date filter is not a Date (the message says what it was). */\nexport function valueMustBeDate(fnName: string, value: unknown): never {\n raise(M.FilterValueNotDate, [fnName, value]);\n}\n\n/** The value given to an array filter is not an array. */\nexport function valueMustBeArray(fnName: string): never {\n raise(M.FilterValueNotArray, [fnName]);\n}\n","/**\n * filters/options.ts — option parsing shared by the core set and the formats add-on, ported\n * verbatim from `@wcstack/state` (`formats/builtinFilters.ts`).\n *\n * Numeric options are read **once, when the filter is built**: the checks stay in one place and the\n * `Number()` conversion stays off the apply path.\n */\nimport { optionMustBeNumber, optionsRequired } from \"./errorMessages\";\n\n/** `\"\"` and anything `Number()` cannot read are rejected (so `lt('')` is an error, not `lt(0)`). */\nexport function validateNumberString(value: string): boolean {\n if (!value || isNaN(Number(value))) {\n return false;\n }\n return true;\n}\n\n/** One numeric option, converted: non-numeric → `optionMustBeNumber`. */\nexport function numberOption(value: string, fnName: string): number {\n if (!validateNumberString(value)) {optionMustBeNumber(fnName);}\n return Number(value);\n}\n\n/** A required numeric option: missing → `optionsRequired`, non-numeric → `optionMustBeNumber`. */\nexport function requiredNumberOption(options: readonly string[] | undefined, index: number, fnName: string): number {\n return numberOption(options?.[index] ?? optionsRequired(fnName), fnName);\n}\n\n/**\n * The typed literal of the first argument (requirement B9): an unquoted `true` / `false` / `null` /\n * number arrives typed, a quoted argument as a string. Without literals (tooling calling a factory\n * directly) the raw option text stands in.\n */\nexport function firstLiteral(opt: string, literals: readonly unknown[] | undefined): unknown {\n return literals !== undefined && literals.length > 0 ? literals[0] : opt;\n}\n","/**\n * filters/core.ts — the core filter set (10): the conditions a binding tests, as opposed to the\n * values the formats add-on (`./formats`) computes and shows. Ported from `@wcstack/state`\n * (`formats/builtinFilters.ts`) with the semantics unchanged.\n *\n * - conditions: `eq ne not lt le gt ge truthy falsy boolean`\n *\n * The arithmetic (`add sub mul div mod abs clamp`), conversion (`number string int float`) and\n * missing-value (`defaults coalesce nullIfEmpty`) filters were here up to 4.0.0-rc.3; they are the\n * formats add-on's since, for the core's size target.\n *\n * `installCoreFilters()` puts them in the registry; the engine calls it before it plans bindings\n * (`else:` is built with an injected `not`, so the core set is never optional).\n */\nimport { optionMustBeNumber, optionsRequired, valueMustBeNumber } from \"./errorMessages\";\nimport { firstLiteral, requiredNumberOption, validateNumberString } from \"./options\";\nimport { registerFilters, type FilterDefinition, type FilterFn } from \"./registry\";\n\n/** Equality — compares with the option (a typed literal compares as itself, B9). */\nconst eq = (options: string[], literals?: readonly unknown[]): FilterFn => {\n const opt = options?.[0] ?? optionsRequired('eq');\n const literal = firstLiteral(opt, literals);\n return (value: unknown): boolean => {\n if (typeof value === 'number') {\n // A typed literal that is not a string compares as itself (B9): a number is never equal to\n // `true` / `false` / `null`, so `selectedId|eq(null)` is false once the id is a number instead\n // of throwing on every apply. Only an unquoted non-number (`eq(abc)`) still reports the type\n // mismatch, and it has to stay here: `eq` accepts values of any type (`status|eq(active)` is\n // valid), so it cannot be rejected at construction the way `lt` / `add` can.\n if (typeof literal !== 'string') {return value === literal;}\n if (!validateNumberString(opt)) {optionMustBeNumber('eq');}\n return value === Number(opt);\n }\n if (typeof value === 'string') {\n return value === opt;\n }\n // Booleans, null and the rest compare with the typed literal: eq(true) matches true (B9)\n return value === literal;\n };\n};\n\n/** Inequality — the negation of `eq`, with the same typing rules (B9). */\nconst ne = (options: string[], literals?: readonly unknown[]): FilterFn => {\n const opt = options?.[0] ?? optionsRequired('ne');\n const literal = firstLiteral(opt, literals);\n return (value: unknown): boolean => {\n if (typeof value === 'number') {\n if (typeof literal !== 'string') {return value !== literal;}\n if (!validateNumberString(opt)) {optionMustBeNumber('ne');}\n return value !== Number(opt);\n }\n if (typeof value === 'string') {\n return value !== opt;\n }\n return value !== literal;\n };\n};\n\n/**\n * Inverts truthiness (lenient `!value`). `else:` is built as the `if` condition plus an injected\n * `not`, and `if:` coerces with `Boolean()`; a strict `not` made `else:` throw — rendering neither\n * branch — whenever the condition was a falsy non-boolean (`0` / `\"\"` / `undefined` / `null`).\n */\nconst not = (): FilterFn => (value: unknown): boolean => !value;\n\n/**\n * A comparison or arithmetic filter: one numeric option, a number value (`lt` … `ge` here, `add` …\n * `mod` in the formats add-on).\n */\nexport const numeric = (name: string, op: (value: number, opt: number) => unknown): FilterDefinition => ({\n factory: (options: string[]): FilterFn => {\n const opt = requiredNumberOption(options, 0, name);\n return (value: unknown): unknown => {\n if (typeof value !== 'number') {valueMustBeNumber(name, value);}\n return op(value, opt);\n };\n },\n arity: [1, 1],\n});\n\n/** JavaScript's truthiness, the same as `boolean` (B10). */\nconst truthy = (): FilterFn => (value: unknown): boolean => !!value;\n\n/** JavaScript's falsiness (`!value`: false, null, undefined, 0, -0, 0n, '' and NaN — B10). */\nconst falsy = (): FilterFn => (value: unknown): boolean => !value;\n\nconst boolean = (): FilterFn => (value: unknown): boolean => Boolean(value);\n\n/**\n * The core set: factory and [min, max] argument count (B3 — the same bounds lint uses).\n *\n * The key order is the source's (`builtinFilterMeta`, which lint reads): the did-you-mean\n * suggestion breaks ties by registration order (see `installFormats` for the order the full\n * build registers).\n */\nexport const coreFilters: Readonly<Record<string, FilterDefinition>> = {\n eq: { factory: eq, arity: [1, 1] },\n ne: { factory: ne, arity: [1, 1] },\n not: { factory: not, arity: [0, 0] },\n lt: numeric('lt', (value, opt) => value < opt),\n le: numeric('le', (value, opt) => value <= opt),\n gt: numeric('gt', (value, opt) => value > opt),\n ge: numeric('ge', (value, opt) => value >= opt),\n falsy: { factory: falsy, arity: [0, 0] },\n truthy: { factory: truthy, arity: [0, 0] },\n boolean: { factory: boolean, arity: [0, 0] },\n};\n\nlet installed = false;\n\n/** Puts the core set in the registry. Idempotent; the engine calls it before planning any binding. */\nexport function installCoreFilters(): void {\n if (installed) return;\n installed = true;\n registerFilters(coreFilters);\n}\n"],"mappings":"gFASO,SAASA,EAAgBC,GAC9BC,KAA+B,CAACD,GAClC,CAGO,SAASE,EAAmBF,GACjCC,KAA+B,CAACD,GAClC,CAGO,SAASG,EAAaH,EAAgBI,GAC3CH,KAA4B,CAACD,EAAQI,GACvC,CAGO,SAASC,EAAgBD,GAC9BH,KAA+B,CAACG,GAClC,CAGO,SAASE,EAAkBN,EAAgBI,GAChDH,KAA8B,CAACD,EAAQI,GACzC,CAGO,SAASG,EAAgBP,EAAgBI,GAC9CH,KAA4B,CAACD,EAAQI,GACvC,CAGO,SAASI,EAAiBR,GAC/BC,KAA6B,CAACD,GAChC,CC/BO,SAASS,EAAqBL,GACnC,SAAKA,GAASM,MAAMC,OAAOP,IAI7B,CAGO,SAASQ,EAAaR,EAAeJ,GAC1C,OAAKS,EAAqBL,IAASF,EAAmBF,GAC/CW,OAAOP,EAChB,CAGO,SAASS,EAAqBC,EAAwCC,EAAef,GAC1F,OAAOY,EAAaE,IAAUC,IAAUhB,EAAgBC,GAASA,EACnE,CAOO,SAASgB,EAAaC,EAAaC,GACxC,YAAoB,IAAbA,GAA0BA,EAASC,OAAS,EAAID,EAAS,GAAKD,CACvE,CChBA,IAkDaG,EAAU,CAACC,EAAcC,MACpCC,QAAUT,IACR,IAAMG,EAAMJ,EAAqBC,EAAS,EAAGO,GAC7C,OAAQjB,IACe,iBAAVA,GAAqBE,EAAkBe,EAAMjB,GACjDkB,EAAGlB,EAAOa,KAGrBO,MAAO,CAAC,EAAG,KAkBAC,EAA0D,CACrEC,GAAI,CAAEH,QA7EG,CAACT,EAAmBI,KAC7B,IAAMD,EAAMH,IAAU,IAAMf,EAAgB,MACtC4B,EAAUX,EAAaC,EAAKC,GAClC,OAAQd,GACe,iBAAVA,EAMc,iBAAZuB,EAA8BvB,IAAUuB,GAC9ClB,EAAqBQ,IAAOf,EAAmB,MAC7CE,IAAUO,OAAOM,IAEL,iBAAVb,EACFA,IAAUa,EAGZb,IAAUuB,GA2DAH,MAAO,CAAC,EAAG,IAC9BI,GAAI,CAAEL,QAvDG,CAACT,EAAmBI,KAC7B,IAAMD,EAAMH,IAAU,IAAMf,EAAgB,MACtC4B,EAAUX,EAAaC,EAAKC,GAClC,OAAQd,GACe,iBAAVA,EACc,iBAAZuB,EAA8BvB,IAAUuB,GAC9ClB,EAAqBQ,IAAOf,EAAmB,MAC7CE,IAAUO,OAAOM,IAEL,iBAAVb,EACFA,IAAUa,EAEZb,IAAUuB,GA2CAH,MAAO,CAAC,EAAG,IAC9BK,IAAK,CAAEN,QAnCG,IAAiBnB,IAA6BA,EAmCnCoB,MAAO,CAAC,EAAG,IAChCM,GAAIV,EAAQ,KAAM,CAAChB,EAAOa,IAAQb,EAAQa,GAC1Cc,GAAIX,EAAQ,KAAM,CAAChB,EAAOa,IAAQb,GAASa,GAC3Ce,GAAIZ,EAAQ,KAAM,CAAChB,EAAOa,IAAQb,EAAQa,GAC1CgB,GAAIb,EAAQ,KAAM,CAAChB,EAAOa,IAAQb,GAASa,GAC3CiB,MAAO,CAAEX,QAnBG,IAAiBnB,IAA6BA,EAmBjCoB,MAAO,CAAC,EAAG,IACpCW,OAAQ,CAAEZ,QAvBG,IAAiBnB,KAA8BA,EAuBjCoB,MAAO,CAAC,EAAG,IACtCY,QAAS,CAAEb,QAnBG,IAAiBnB,KAAoCA,EAmBtCoB,MAAO,CAAC,EAAG,KAGtCa,GAAY,EAGT,SAASC,IACVD,IACJA,GAAY,EACZE,EAAgBd,GAClB,QAAAe,OAAAC,OAAAC,OAAAC,OAAAC,OAAAC,OAAAC,OAAAC,OAAAC,OAAAC,OAAAC,OAAAC","ignoreList":[]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{b as t,c as e,d as s}from"./chunk-
|
|
2
|
-
//# sourceMappingURL=chunk-
|
|
1
|
+
import{b as t,c as e,d as s}from"./chunk-BYQBV3ZC.js";import{n as i,o as n}from"./chunk-4ECL4ITF.js";import{f as o}from"./chunk-BI4645UG.js";import{a,b as r}from"./chunk-CIBJLAA3.js";import{a as l,b as c}from"./chunk-UBGJGMSG.js";import{a as h,h as u,i as d}from"./chunk-BGUJ3HF6.js";var m=0,f=new WeakMap;function p(t,e=t.getRootNode()){f.set(e,[...f.get(e)??[],t].filter((t,e,s)=>t.isConnected&&s.lastIndexOf(t)===e))}function b(t){let e=f.get(t)??[],s=e.filter(e=>e.getRootNode()===t);return Promise.any(s.map(t=>t.initializePromise.then(()=>t.V||t.connectedCallbackPromise))).then(()=>{},i=>s.length?f.get(t)!==e?b(t):Promise.reject(i.errors[0]):void 0)}var g=typeof HTMLElement>"u"?class{}:HTMLElement,w=class extends g{constructor(){super(),this.engine=null,this.jn=!1,this.qe=!1,this.U=null,this.Ge=null,this.loaded=!1,this.un=null,this.connectedCallbackPromise=new Promise((t,e)=>{this.cn=t,this.Eo=e}),this.connectedCallbackPromise.catch(()=>{}),this.initializePromise=new Promise(t=>{this.an=t})}static{this.getBindingsReady=b}static{this.hasConnectedCallbackPromise=!0}connectedCallback(){if(this.jn){if(null!==this.Ge)return void this.Ge.Je();p(this);let e=this.engine;if(null!==e){let s=e.root;s===this.getRootNode()&&!i.has(s)&&i.set(s,e),t(),h.element?.(e,"back"),this.No("$connectedCallback",50,()=>{this.isConnected&&h.element?.(e,"connected")})}return}this.jn=!0;let e=this.getRootNode(),s=h.ct?.(this,e);if(s)return this.Ge=s,!s.xo&&this.parentNode instanceof ShadowRoot&&p(this),void(void 0===s.bt?this.Ro():s.bt()).then(t=>(this.loaded=!0,s.start(t,()=>this.Po()))).then(()=>{this.an(),this.cn()},t=>this.xt(t,s.xo));this.start(e),p(this)}disconnectedCallback(){if(null!==this.Ge)return void this.Ge.Ln();let t=this.engine;if(null===t)return;let e=t.root;i.get(e)===t&&i.delete(e),p(this,e),this.No("$disconnectedCallback",51),h.element?.(t,"disconnected")}setInitialState(t){if(this.qe&&c(14),this.loaded)this.Ge.reset(t);else if(null===this.engine)if(null!==this.un){let e=this.un;this.un=null,e(t)}else this.U=t;else this.engine.reset(t)}createState(t,e){let s=this.engine;null===s&&c(15),"readonly"===t&&s.Le++;try{e(s.proxy)}finally{"readonly"===t&&s.Le--}}async createStateAsync(t,e){let s=this.engine;null===s&&c(15),await e("writable"===t?s.proxy:new Proxy(s.proxy,{get(t,e,s){let i=Reflect.get(t,e,s);return"$setAll"===e||"$resolve"===e?(...t)=>(t.length>2&&c(8),i(...t)):i},set(){c(8)}}))}async Ro(){await 0;let t=this.getAttribute("state");if(null!==t){let e=e=>[...e.querySelectorAll('script[type="application/json"]')].find(e=>e.id===t),s=e(this.getRootNode())??e(document);return void 0===s?Promise.reject(new Error(`[@wcstack/state] ${l(16,[t])}`)):Promise.resolve(JSON.parse(s.textContent||"{}"))}let e=this.getAttribute("src");if(null!==e)return async function(t){let e=new URL(t,document.baseURI).href;if(/\.json(?:[?#]|$)/.test(e)){let s=await fetch(e);return s.ok||c(13,[t,s.status]),await s.json()}return(await(import(e))).default??{}}(e);let s=this.getAttribute("json");if(null!==s)return Promise.resolve(JSON.parse(s));let i=this.querySelector('script[type="module"]');return null!==i?async function(t){let e=!1,s=t=>{t.effectiveDirective.startsWith("script-src")&&(e=!0)};document.addEventListener("securitypolicyviolation",s);let i="function"==typeof URL.createObjectURL,n=i?URL.createObjectURL(new Blob([t.text],{type:"application/javascript"})):"data:text/javascript;charset=utf-8,"+encodeURIComponent(`${t.text}\n//${++m}`);try{return(await(import(n))).default??{}}catch(t){throw await new Promise(t=>setTimeout(t)),new Error(`[@wcstack/state] ${e?l(42):l(43,[t instanceof Error?t.message:String(t)])}`,{cause:t})}finally{document.removeEventListener("securitypolicyviolation",s),i&&URL.revokeObjectURL(n)}}(i):null!==this.U?Promise.resolve(this.U):new Promise(t=>{this.un=t})}async start(e){try{let a=e.host;(this.hasAttribute("mount")||this.hasAttribute("bind-component")||a?.hasAttribute("data-wc-definition"))&&d("scopes","<wcs-state>");let r=await this.Ro(),l=u(r);if(l&&await l,this.getRootNode()!==e)return this.U=r,this.jn=!1,void(this.isConnected&&this.connectedCallback());this.hasAttribute("enable-ssr")&&d("ssr","enable-ssr");let m=i.get(e)?.element;m?.isConnected&&(m.V||m.Ge)&&c(47);let f=new o(r,new s);f.element=this,this.engine=f,h.element?.(f,"mounting"),n(f,e),t(),f.En(),this.Po(),await f.Se("$connectedCallback"),this.isConnected&&h.element?.(f,"connected"),this.cn()}catch(t){this.qe=!this.V,this.xt(t)}}Po(){this.V=!0,this.an()}xt(t,e){this.Ue(this.V?50:49,t),this.an(),e?this.cn():this.Eo(t)}Ue(t,e){let s=["mount","bind-component","state","src"].flatMap(t=>this.hasAttribute(t)?[t,this.getAttribute(t)]:[]);console.error(`[@wcstack/state] ${l(t,[this.localName,...s])}`,e)}No(t,e,s){(async()=>this.engine.Se(t))().then(s,t=>this.Ue(e,t))}},y=[];function v(){return(y=y.filter(t=>t.deref())).map(t=>t.deref())}function k(t,s){t&&r(t),function(t=customElements){e(),v().includes(t)||y.push(new WeakRef(t));let s=a.tagNames.state;void 0===t.get(s)&&t.define(s,class extends w{}),h.To?.(t)}(s)}var R=t=>b(t);export{b as a,g as b,v as c,k as d,R as e};
|
|
2
|
+
//# sourceMappingURL=chunk-3Q7LGONS.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["loads","readyByRoot","WeakMap","enroll","el","root","getRootNode","set","get","filter","e","i","a","isConnected","lastIndexOf","getBindingsReady","list","els","Promise","any","map","initializePromise","then","bound","connectedCallbackPromise","length","reject","errors","HTMLElementBase","HTMLElement","WcsState","constructor","super","this","engine","started","failed","initial","claimed","loaded","receiveInitial","resolve","resolveConnected","rejectConnected","catch","resolveInitialize","hasConnectedCallbackPromise","connectedCallback","connected","engines","has","drainBinds","hooks","element","rerun","claim","lenient","parentNode","ShadowRoot","load","loadState","state","start","built","fail","disconnectedCallback","disconnected","delete","setInitialState","raise","reset","receive","createState","mutability","callback","readonlyDepth","proxy","createStateAsync","Proxy","t","k","receiver","v","Reflect","id","getAttribute","find","r","querySelectorAll","x","script","document","Error","text","JSON","parse","textContent","src","async","url","URL","baseURI","href","test","res","fetch","ok","status","json","default","loadSrc","querySelector","blocked","seen","effectiveDirective","startsWith","addEventListener","blob","createObjectURL","Blob","type","encodeURIComponent","setTimeout","message","String","cause","removeEventListener","revokeObjectURL","loadInnerScript","host","hasAttribute","requireFeature","loading","loadFeatures","other","Engine","DirtyStrategy","mount","watchRendered","callHook","report","at","flatMap","n","console","error","localName","name","refs","registries","deref","bootstrapState","partial","registry","setConfig","customElements","installBinder","includes","push","WeakRef","tag","config","tagNames","define","tags","buildBindings","b","j","I","z","q"],"sources":["../../../src/element.ts"],"sourcesContent":["import type { IWritableConfig } from \"./public/types\";\nimport { Engine } from \"./engine\";\nimport { engines, mount } from \"./dom/mount\";\nimport { drainBinds, installBinder } from \"./dom/binder\";\nimport { DirtyStrategy } from \"./strategy/dirty\";\nimport { config, setConfig } from \"./config\";\nimport type { Strategy } from \"./strategy/types\";\nimport { raise, M, text } from \"./messages\";\nimport { hooks, loadFeatures, requireFeature, type Claimed } from \"./hooks\";\n\nlet makeStrategy: () => Strategy = () => new DirtyStrategy();\n\n/** Chooses the invalidation strategy of every engine created from now on. */\nexport function configure(factory: () => Strategy): void {\n makeStrategy = factory;\n}\n\nlet loads = 0;\n\nasync function loadInnerScript(script: HTMLScriptElement): Promise<Record<string, any>> {\n // an import a Content-Security-Policy blocked rejects without saying why: the violation event\n // is the only witness (docs/csp.md §9)\n let blocked = false;\n const seen = (e: SecurityPolicyViolationEvent): void => {\n if (e.effectiveDirective.startsWith(\"script-src\")) blocked = true;\n };\n document.addEventListener(\"securitypolicyviolation\", seen);\n // a server (@wcstack/server) removes createObjectURL: a data: URL, unique so no load is cached\n const blob = typeof URL.createObjectURL === \"function\";\n const url = blob\n ? URL.createObjectURL(new Blob([script.text], { type: \"application/javascript\" }))\n : \"data:text/javascript;charset=utf-8,\" + encodeURIComponent(`${script.text}\\n//${++loads}`);\n try {\n const mod = await import(/* @vite-ignore */ url);\n return (mod.default ?? {}) as Record<string, any>;\n } catch (e) {\n // Firefox fires the violation a task after the rejection (Chromium and WebKit before it)\n await new Promise((r) => setTimeout(r));\n throw new Error(`[@wcstack/state] ${blocked ? text(M.InlineBlocked) : text(M.InlineFailed, [e instanceof Error ? e.message : String(e)])}`, { cause: e });\n } finally {\n document.removeEventListener(\"securitypolicyviolation\", seen);\n if (blob) URL.revokeObjectURL(url);\n }\n}\n\nasync function loadSrc(src: string): Promise<Record<string, any>> {\n const url = new URL(src, document.baseURI).href;\n if (/\\.json(?:[?#]|$)/.test(url)) {\n const res = await fetch(url);\n if (!res.ok) raise(M.LoadFailed, [src, res.status]);\n return (await res.json()) as Record<string, any>;\n }\n const mod = await import(/* @vite-ignore */ url);\n return (mod.default ?? {}) as Record<string, any>;\n}\n\n/**\n * The root `<wcs-state>` elements of each root node (and the one a component mount or a DCC definition\n * has in its shadow root): a new list whenever one connects, without the ones no longer in the page.\n */\nconst readyByRoot = new WeakMap<Node, WcsState[]>();\n\n/**\n * Puts `el` among the `<wcs-state>` elements of `root` (a new list, without the ones that left) — or,\n * taken out of it, takes it off: the list holds nothing of a page that went.\n */\nfunction enroll(el: WcsState, root: Node = el.getRootNode()): void {\n readyByRoot.set(root, [...(readyByRoot.get(root) ?? []), el].filter((e, i, a) => e.isConnected && a.lastIndexOf(e) === i));\n}\n\n/**\n * Resolves when the bindings of `root` are built — by any `<wcs-state>` in it now, whatever its\n * `$connectedCallback` does then, as 3.x — and rejects, with the first failure, only when every one\n * failed before building them. A stray one (a second root, #47; one that fails to load) changes\n * nothing while another binds the root; one taken out of the page (or moved to another root) counts\n * no more (a root replaced: the new one decides). With none in it — none ever, or only ones that left —\n * it resolves at once: there is nothing to wait for (a page without state).\n */\nexport function getBindingsReady(root: Node): Promise<void> {\n const list = readyByRoot.get(root) ?? [];\n const els = list.filter((e) => e.getRootNode() === root);\n return Promise.any(els.map((el) => el.initializePromise.then((): unknown => el.bound || el.connectedCallbackPromise))).then(\n () => {},\n // none, or every one failed: one connected since (the list is a new one) may still bind the root\n // (quoted: `errors` is a name the build shortens, an AggregateError's is not)\n (e: AggregateError) => (els.length ? readyByRoot.get(root) !== list ? getBindingsReady(root) : Promise.reject(e[\"errors\"][0]) : undefined),\n );\n}\n\n/**\n * The base of the package's elements: HTMLElement, or — where there is none (Node without a DOM)\n * — an inert class, so the entries can be imported headless (a tool reading the manifest, a\n * server framework importing at the top level), as 3.x. Making an element stays a browser's.\n */\nexport const HTMLElementBase = (typeof HTMLElement === \"undefined\" ? class {} : HTMLElement) as typeof HTMLElement;\n\n/**\n * `<wcs-state>` — one engine per element, bound to the element's root node.\n * State resolution order: `state` (id of a JSON script) → `src` → `json` → inner\n * `<script type=\"module\">` → wait for `setInitialState()`.\n */\nexport class WcsState extends HTMLElementBase {\n static getBindingsReady = getBindingsReady;\n /** Servers (@wcstack/server) wait on connectedCallbackPromise when this is set. */\n static hasConnectedCallbackPromise = true;\n\n engine: Engine | null = null;\n readonly connectedCallbackPromise: Promise<void>;\n /**\n * Resolves once the state is loaded and bound (before `$connectedCallback`) — and also when\n * initialization fails: the failure is delivered on connectedCallbackPromise.\n */\n readonly initializePromise: Promise<void>;\n private resolveInitialize!: () => void;\n private resolveConnected!: () => void;\n private rejectConnected!: (e: unknown) => void;\n private started = false;\n /** Initialization failed before the page was bound: `setInitialState` refuses (#14). */\n private failed = false;\n private initial: Record<string, any> | null = null;\n /** Taken over by an add-on (a volume, a DCC definition): it never becomes a root. */\n private claimed: Claimed | null = null;\n /** A claimed element's state is loaded: `setInitialState` from now on is the add-on's re-set. */\n private loaded = false;\n /** The root's bindings are built (getBindingsReady resolves, whatever `$connectedCallback` does). */\n bound?: boolean;\n private receiveInitial: ((state: Record<string, any>) => void) | null = null;\n\n constructor() {\n super();\n this.connectedCallbackPromise = new Promise<void>((resolve, reject) => {\n this.resolveConnected = resolve;\n this.rejectConnected = reject;\n });\n this.connectedCallbackPromise.catch(() => {});\n this.initializePromise = new Promise<void>((resolve) => {\n this.resolveInitialize = resolve;\n });\n }\n\n connectedCallback(): void {\n if (this.started) {\n if (this.claimed !== null) {\n this.claimed.connected();\n return;\n }\n enroll(this);\n const engine = this.engine;\n if (engine !== null) {\n // back in the page: it holds its root again (unless another <wcs-state> bound it meanwhile),\n // binds what was handed over while it was out, and the add-ons hear of it (the volumes that\n // connected meanwhile graft) — then $connectedCallback runs again\n const root = engine.root;\n if (root === this.getRootNode() && !engines.has(root)) engines.set(root, engine);\n drainBinds();\n hooks.element?.(engine, \"back\");\n this.rerun(\"$connectedCallback\", M.ConnectedFailed, () => {\n if (this.isConnected) hooks.element?.(engine, \"connected\");\n });\n }\n return;\n }\n this.started = true;\n const root = this.getRootNode();\n const claimed = hooks.claim?.(this, root);\n if (claimed) {\n this.claimed = claimed;\n // the `<wcs-state>` of the shadow root it binds (a component's, a DCC definition's) is that\n // root's, as 3.x: getBindingsReady there waits for it — until its bindings are built, as a\n // root's — and fails with it (a volume never fails)\n if (!claimed.lenient && this.parentNode instanceof ShadowRoot) enroll(this);\n void (claimed.load === undefined ? this.loadState() : claimed.load()).then((state) => {\n this.loaded = true;\n return claimed.start(state, () => this.built());\n }).then(() => {\n this.resolveInitialize();\n this.resolveConnected();\n }, (e) => this.fail(e, claimed.lenient));\n return;\n }\n void this.start(root);\n enroll(this);\n }\n\n disconnectedCallback(): void {\n if (this.claimed !== null) {\n this.claimed.disconnected();\n return;\n }\n const engine = this.engine;\n if (engine === null) return;\n // out of the page, it lets go of its root (it holds it again when it is back): what outlives the\n // page's content — its root node, the document — does not keep its state and the DOM it bound\n // (a root that failed before its mount has none: enroll takes the root it is in now)\n const root = engine.root;\n if (engines.get(root!) === engine) engines.delete(root!);\n enroll(this, root);\n this.rerun(\"$disconnectedCallback\", M.DisconnectedFailed);\n hooks.element?.(engine, \"disconnected\");\n }\n\n /**\n * Supplies the initial state; on an initialized element, replaces the whole state and\n * re-applies every binding to it before returning (not a write: no `$renderedCallback`).\n */\n setInitialState(state: Record<string, any>): void {\n if (this.failed) raise(M.ElementFailed);\n // (until a claimed element's state is loaded, this supplies it like a root's)\n if (this.loaded) {\n this.claimed!.reset(state);\n return;\n }\n if (this.engine !== null) {\n this.engine.reset(state);\n return;\n }\n if (this.receiveInitial !== null) {\n const receive = this.receiveInitial;\n this.receiveInitial = null;\n receive(state);\n } else {\n this.initial = state;\n }\n }\n\n /** Runs `callback` with a state proxy; its writes are applied in the next drain. */\n createState(mutability: \"readonly\" | \"writable\", callback: (state: Record<string, any>) => void): void {\n const engine = this.engine;\n if (engine === null) raise(M.NotInitialized);\n if (mutability === \"readonly\") engine.readonlyDepth++;\n try {\n callback(engine.proxy);\n } finally {\n if (mutability === \"readonly\") engine.readonlyDepth--;\n }\n }\n\n /** `createState` whose callback may await; a readonly proxy stays readonly across its awaits. */\n async createStateAsync(mutability: \"readonly\" | \"writable\", callback: (state: Record<string, any>) => Promise<void>): Promise<void> {\n const engine = this.engine;\n if (engine === null) raise(M.NotInitialized);\n await callback(mutability === \"writable\" ? engine.proxy : new Proxy(engine.proxy, {\n // as in createState(\"readonly\"), the writes of $setAll and $resolve (path, indexes, value) refuse;\n // read with this view as the receiver, a method comes as it is and runs on this view\n get(t, k, receiver) {\n const v = Reflect.get(t, k, receiver);\n return k === \"$setAll\" || k === \"$resolve\" ? (...a: unknown[]) => (a.length > 2 && raise(M.Readonly), v(...a)) : v;\n },\n set() {\n raise(M.Readonly);\n },\n }));\n }\n\n private async loadState(): Promise<Record<string, any>> {\n // a parser that inserts the element before its children (a server render) has added them by now\n await 0;\n const id = this.getAttribute(\"state\");\n if (id !== null) {\n // a JSON script of that id (an element of user content with the same id, earlier, is not it)\n const find = (r: Node): HTMLScriptElement | undefined =>\n [...(r as Document).querySelectorAll<HTMLScriptElement>('script[type=\"application/json\"]')].find((x) => x.id === id);\n const script = find(this.getRootNode()) ?? find(document);\n if (script === undefined) return Promise.reject(new Error(`[@wcstack/state] ${text(M.NoScript, [id])}`));\n return Promise.resolve(JSON.parse(script.textContent || \"{}\"));\n }\n const src = this.getAttribute(\"src\");\n if (src !== null) return loadSrc(src);\n const json = this.getAttribute(\"json\");\n if (json !== null) return Promise.resolve(JSON.parse(json));\n const script = this.querySelector('script[type=\"module\"]') as HTMLScriptElement | null;\n if (script !== null) return loadInnerScript(script);\n if (this.initial !== null) return Promise.resolve(this.initial);\n return new Promise((resolve) => {\n this.receiveInitial = resolve;\n });\n }\n\n private async start(root: Node): Promise<void> {\n try {\n // what an add-on serves: a volume, a component mount, a DCC definition, server rendering\n const host = (root as ShadowRoot).host;\n if (this.hasAttribute(\"mount\") || this.hasAttribute(\"bind-component\") || host?.hasAttribute(\"data-wc-definition\")) {\n requireFeature(\"scopes\", \"<wcs-state>\");\n }\n const state = await this.loadState();\n const loading = loadFeatures(state);\n if (loading) await loading;\n // taken out of its root while it loaded (the page's content replaced, or moved to another root):\n // nothing is mounted on the root it left. It starts again where it is now, or when it connects\n // again. A state given by setInitialState() is kept for that; a state= / src= / json= / inline\n // script source is read again (a fetch runs again, an inline module is evaluated again)\n if (this.getRootNode() !== root) {\n this.initial = state;\n this.started = false;\n if (this.isConnected) this.connectedCallback();\n return;\n }\n if (this.hasAttribute(\"enable-ssr\")) requireFeature(\"ssr\", \"enable-ssr\");\n // one state tree per root: another <wcs-state> already bound this root (and still does —\n // whatever its $connectedCallback did then), or a component's took it\n const other = engines.get(root)?.element as WcsState | undefined;\n if (other?.isConnected && (other.bound || other.claimed)) raise(M.SecondRoot);\n const engine = new Engine(state, makeStrategy());\n engine.element = this;\n this.engine = engine;\n hooks.element?.(engine, \"mounting\");\n mount(engine, root as Document | ShadowRoot);\n drainBinds();\n engine.watchRendered();\n this.built();\n await engine.callHook(\"$connectedCallback\");\n if (this.isConnected) hooks.element?.(engine, \"connected\");\n this.resolveConnected();\n } catch (e) {\n // (a root that bound its page and whose $connectedCallback then failed has not: re-set stays open)\n this.failed = !this.bound;\n this.fail(e);\n }\n }\n\n /** The bindings are built (before `$connectedCallback`): getBindingsReady resolves, initializePromise too. */\n private built(): void {\n this.bound = true;\n this.resolveInitialize();\n }\n\n /**\n * Initialization failed: reported once, the element (and where its state comes from) before what\n * was thrown, as 3.5 — `<wcs-state src=\"./state.js\"> failed to initialize.`, or, once its\n * bindings were built, `… $connectedCallback failed.` — and connectedCallbackPromise rejects with\n * it, or resolves for a claim that is `lenient` (a volume).\n */\n private fail(e: unknown, lenient?: boolean): void {\n this.report(this.bound ? M.ConnectedFailed : M.InitFailed, e);\n this.resolveInitialize();\n if (lenient) this.resolveConnected();\n else this.rejectConnected(e);\n }\n\n /** Reports a failure once: the element (and where its state comes from), then what was thrown. */\n private report(id: M, e: unknown): void {\n const at = [\"mount\", \"bind-component\", \"state\", \"src\"].flatMap((n) => (this.hasAttribute(n) ? [n, this.getAttribute(n)] : []));\n console.error(`[@wcstack/state] ${text(id, [this.localName, ...at])}`, e);\n }\n\n /**\n * Runs a lifecycle callback of a root that connected before (on reconnect, on disconnect) at once: a\n * failure — thrown or rejected — is reported as a first connection's is, never thrown out of the\n * element's callback.\n */\n private rerun(name: string, id: M, then?: () => void): void {\n void (async () => this.engine!.callHook(name))().then(then, (e) => this.report(id, e));\n }\n}\n\n/**\n * The registries `<wcs-state>` was defined in: an add-on installed later defines its tags there\n * too. Weak: a server creates a registry per render, and holding them would keep every render's\n * registry (and every constructor defined in it) alive.\n */\nlet refs: WeakRef<CustomElementRegistry>[] = [];\n\n/**\n * The registries still alive (dead references are dropped). A registry deref() returned stays\n * alive until the end of this job, so the second deref() of each kept reference finds it.\n */\nexport function registries(): CustomElementRegistry[] {\n refs = refs.filter((r) => r.deref());\n return refs.map((r) => r.deref()!);\n}\n\n/**\n * Registers `<wcs-state>` (and the installed add-ons' tags) in `registry` — a scoped registry\n * does not inherit the global one, so a tree using one needs its own definitions.\n */\nexport function define(registry: CustomElementRegistry = customElements): void {\n installBinder();\n if (!registries().includes(registry)) refs.push(new WeakRef(registry));\n const tag = config.tagNames.state;\n if (registry.get(tag) === undefined) registry.define(tag, class extends WcsState {});\n hooks.tags?.(registry);\n}\n\n/** Applies `config` and registers `<wcs-state>`. The core only: install the add-ons first. */\nexport function bootstrapState(partial?: IWritableConfig, registry?: CustomElementRegistry): void {\n if (partial) setConfig(partial);\n define(registry);\n}\n\n/**\n * Waits for the bindings under `root` (3.x built them here; the new engine builds them when the\n * root's `<wcs-state>` loads its state, so this only waits — the same as getBindingsReady).\n */\nexport const buildBindings = (root: Document | ShadowRoot): Promise<void> => getBindingsReady(root);\n"],"mappings":"4RAUA,IAOIA,EAAQ,EA2CNC,EAAc,IAAIC,QAMxB,SAASC,EAAOC,EAAcC,EAAaD,EAAGE,eAC5CL,EAAYM,IAAIF,EAAM,IAAKJ,EAAYO,IAAIH,IAAS,GAAKD,GAAIK,OAAO,CAACC,EAAGC,EAAGC,IAAMF,EAAEG,aAAeD,EAAEE,YAAYJ,KAAOC,GACzH,CAUO,SAASI,EAAiBV,GAC/B,IAAMW,EAAOf,EAAYO,IAAIH,IAAS,GAChCY,EAAMD,EAAKP,OAAQC,GAAMA,EAAEJ,gBAAkBD,GACnD,OAAOa,QAAQC,IAAIF,EAAIG,IAAKhB,GAAOA,EAAGiB,kBAAkBC,KAAK,IAAelB,EAAGmB,GAASnB,EAAGoB,4BAA4BF,KACrH,OAGCZ,GAAuBO,EAAIQ,OAASxB,EAAYO,IAAIH,KAAUW,EAAOD,EAAiBV,GAAQa,QAAQQ,OAAOhB,EAAEiB,OAAU,SAAM,EAEpI,CAOO,IAAMC,SAA0BC,YAAgB,IAAc,QAAWA,YAOnEC,EAAN,cAAuBF,EA2B5B,WAAAG,GACEC,QAvBFC,KAAAC,OAAwB,KAUxBD,KAAQE,IAAU,EAElBF,KAAQG,IAAS,EACjBH,KAAQI,EAAsC,KAE9CJ,KAAQK,GAA0B,KAElCL,KAAQM,QAAS,EAGjBN,KAAQO,GAAgE,KAItEP,KAAKT,yBAA2B,IAAIN,QAAc,CAACuB,EAASf,KAC1DO,KAAKS,GAAmBD,EACxBR,KAAKU,GAAkBjB,IAEzBO,KAAKT,yBAAyBoB,MAAM,QACpCX,KAAKZ,kBAAoB,IAAIH,QAAeuB,IAC1CR,KAAKY,GAAoBJ,GAE7B,QApCAR,KAAOlB,iBAAmBA,SAE1BkB,KAAOa,6BAA8B,EAoCrC,iBAAAC,GACE,GAAId,KAAKE,GAAS,CAChB,GAAqB,OAAjBF,KAAKK,GAEP,YADAL,KAAKK,GAAQU,KAGf7C,EAAO8B,MACP,IAAMC,EAASD,KAAKC,OACpB,GAAe,OAAXA,EAAiB,CAInB,IAAM7B,EAAO6B,EAAO7B,KAChBA,IAAS4B,KAAK3B,gBAAkB2C,EAAQC,IAAI7C,IAAO4C,EAAQ1C,IAAIF,EAAM6B,GACzEiB,IACAC,EAAMC,UAAUnB,EAAQ,QACxBD,KAAKqB,GAAM,wBAAyC,KAC9CrB,KAAKpB,aAAauC,EAAMC,UAAUnB,EAAQ,cAElD,CACA,MACF,CACAD,KAAKE,IAAU,EACf,IAAM9B,EAAO4B,KAAK3B,cACZgC,EAAUc,EAAMG,KAAQtB,KAAM5B,GACpC,GAAIiC,EAaF,OAZAL,KAAKK,GAAUA,GAIVA,EAAQkB,IAAWvB,KAAKwB,sBAAsBC,YAAYvD,EAAO8B,gBAC/C,IAAjBK,EAAQqB,GAAqB1B,KAAK2B,KAActB,EAAQqB,MAAQrC,KAAMuC,IAC1E5B,KAAKM,QAAS,EACPD,EAAQwB,MAAMD,EAAO,IAAM5B,KAAK8B,QACtCzC,KAAK,KACNW,KAAKY,KACLZ,KAAKS,MACHhC,GAAMuB,KAAK+B,GAAKtD,EAAG4B,EAAQkB,KAG5BvB,KAAK6B,MAAMzD,GAChBF,EAAO8B,KACT,CAEA,oBAAAgC,GACE,GAAqB,OAAjBhC,KAAKK,GAEP,YADAL,KAAKK,GAAQ4B,KAGf,IAAMhC,EAASD,KAAKC,OACpB,GAAe,OAAXA,EAAiB,OAIrB,IAAM7B,EAAO6B,EAAO7B,KAChB4C,EAAQzC,IAAIH,KAAW6B,GAAQe,EAAQkB,OAAO9D,GAClDF,EAAO8B,KAAM5B,GACb4B,KAAKqB,GAAM,4BACXF,EAAMC,UAAUnB,EAAQ,eAC1B,CAMA,eAAAkC,CAAgBP,GAGd,GAFI5B,KAAKG,IAAQiC,MAEbpC,KAAKM,OACPN,KAAKK,GAASgC,MAAMT,QAGtB,GAAoB,OAAhB5B,KAAKC,OAIT,GAA4B,OAAxBD,KAAKO,GAAyB,CAChC,IAAM+B,EAAUtC,KAAKO,GACrBP,KAAKO,GAAiB,KACtB+B,EAAQV,EACV,MACE5B,KAAKI,EAAUwB,OARf5B,KAAKC,OAAOoC,MAAMT,EAUtB,CAGA,WAAAW,CAAYC,EAAqCC,GAC/C,IAAMxC,EAASD,KAAKC,OACL,OAAXA,GAAiBmC,MACF,aAAfI,GAA2BvC,EAAOyC,KACtC,IACED,EAASxC,EAAO0C,MAClB,SACqB,aAAfH,GAA2BvC,EAAOyC,IACxC,CACF,CAGA,sBAAME,CAAiBJ,EAAqCC,GAC1D,IAAMxC,EAASD,KAAKC,OACL,OAAXA,GAAiBmC,YACfK,EAAwB,aAAfD,EAA4BvC,EAAO0C,MAAQ,IAAIE,MAAM5C,EAAO0C,MAAO,CAGhF,GAAApE,CAAIuE,EAAGC,EAAGC,GACR,IAAMC,EAAIC,QAAQ3E,IAAIuE,EAAGC,EAAGC,GAC5B,MAAa,YAAND,GAAyB,aAANA,EAAmB,IAAIpE,KAAkBA,EAAEa,OAAS,GAAK4C,KAAmBa,KAAKtE,IAAMsE,CACnH,EACA,GAAA3E,GACE8D,IACF,IAEJ,CAEA,QAAcT,SAEN,EACN,IAAMwB,EAAKnD,KAAKoD,aAAa,SAC7B,GAAW,OAAPD,EAAa,CAEf,IAAME,EAAQC,GACZ,IAAKA,EAAeC,iBAAoC,oCAAoCF,KAAMG,GAAMA,EAAEL,KAAOA,GAC7GM,EAASJ,EAAKrD,KAAK3B,gBAAkBgF,EAAKK,UAChD,YAAe,IAAXD,EAA6BxE,QAAQQ,OAAO,IAAIkE,MAAM,oBAAoBC,KAAiB,CAACT,QACzFlE,QAAQuB,QAAQqD,KAAKC,MAAML,EAAOM,aAAe,MAC1D,CACA,IAAMC,EAAMhE,KAAKoD,aAAa,OAC9B,GAAY,OAARY,EAAc,OA9NtBC,eAAuBD,GACrB,IAAME,EAAM,IAAIC,IAAIH,EAAKN,SAASU,SAASC,KAC3C,GAAI,mBAAmBC,KAAKJ,GAAM,CAChC,IAAMK,QAAYC,MAAMN,GACxB,OAAKK,EAAIE,IAAIrC,KAAoB,CAAC4B,EAAKO,EAAIG,eAC7BH,EAAII,MACpB,CAEA,oBAD4CT,KAChCU,SAAW,CAAC,CAC1B,CAqN6BC,CAAQb,GACjC,IAAMW,EAAO3E,KAAKoD,aAAa,QAC/B,GAAa,OAATuB,EAAe,OAAO1F,QAAQuB,QAAQqD,KAAKC,MAAMa,IACrD,IAAMlB,EAASzD,KAAK8E,cAAc,yBAClC,OAAe,OAAXrB,EA5PRQ,eAA+BR,GAG7B,IAAIsB,GAAU,EACRC,EAAQvG,IACRA,EAAEwG,mBAAmBC,WAAW,gBAAeH,GAAU,IAE/DrB,SAASyB,iBAAiB,0BAA2BH,GAErD,IAAMI,EAAsC,mBAAxBjB,IAAIkB,gBAClBnB,EAAMkB,EACRjB,IAAIkB,gBAAgB,IAAIC,KAAK,CAAC7B,EAAOG,MAAO,CAAE2B,KAAM,4BACpD,sCAAwCC,mBAAmB,GAAG/B,EAAOG,aAAa7F,KACtF,IAEE,oBAD4CmG,KAChCU,SAAW,CAAC,CAC1B,OAASnG,GAEP,YAAM,IAAIQ,QAASqE,GAAMmC,WAAWnC,IAC9B,IAAIK,MAAM,oBAAoBoB,EAAUnB,MAAwBA,KAAqB,CAACnF,aAAakF,MAAQlF,EAAEiH,QAAUC,OAAOlH,OAAQ,CAAEmH,MAAOnH,GACvJ,SACEiF,SAASmC,oBAAoB,0BAA2Bb,GACpDI,GAAMjB,IAAI2B,gBAAgB5B,EAChC,CACF,CAoOgC6B,CAAgBtC,GACvB,OAAjBzD,KAAKI,EAAyBnB,QAAQuB,QAAQR,KAAKI,GAChD,IAAInB,QAASuB,IAClBR,KAAKO,GAAiBC,GAE1B,CAEA,WAAcqB,CAAMzD,GAClB,IAEE,IAAM4H,EAAQ5H,EAAoB4H,MAC9BhG,KAAKiG,aAAa,UAAYjG,KAAKiG,aAAa,mBAAqBD,GAAMC,aAAa,wBAC1FC,EAAe,SAAU,eAE3B,IAAMtE,QAAc5B,KAAK2B,KACnBwE,EAAUC,EAAaxE,GAM7B,GALIuE,SAAeA,EAKfnG,KAAK3B,gBAAkBD,EAIzB,OAHA4B,KAAKI,EAAUwB,EACf5B,KAAKE,IAAU,OACXF,KAAKpB,aAAaoB,KAAKc,qBAGzBd,KAAKiG,aAAa,eAAeC,EAAe,MAAO,cAG3D,IAAMG,EAAQrF,EAAQzC,IAAIH,IAAOgD,QAC7BiF,GAAOzH,cAAgByH,EAAM/G,GAAS+G,EAAMhG,KAAU+B,MAC1D,IAAMnC,EAAS,IAAIqG,EAAO1E,EArSS,IAAI2E,GAsSvCtG,EAAOmB,QAAUpB,KACjBA,KAAKC,OAASA,EACdkB,EAAMC,UAAUnB,EAAQ,YACxBuG,EAAMvG,EAAQ7B,GACd8C,IACAjB,EAAOwG,KACPzG,KAAK8B,WACC7B,EAAOyG,GAAS,sBAClB1G,KAAKpB,aAAauC,EAAMC,UAAUnB,EAAQ,aAC9CD,KAAKS,IACP,OAAShC,GAEPuB,KAAKG,IAAUH,KAAKV,EACpBU,KAAK+B,GAAKtD,EACZ,CACF,CAGQqD,KACN9B,KAAKV,GAAQ,EACbU,KAAKY,IACP,CAQQmB,GAAKtD,EAAY8C,GACvBvB,KAAK2G,GAAO3G,KAAKV,QAA0Cb,GAC3DuB,KAAKY,KACDW,EAASvB,KAAKS,KACbT,KAAKU,GAAgBjC,EAC5B,CAGQkI,GAAOxD,EAAO1E,GACpB,IAAMmI,EAAK,CAAC,QAAS,iBAAkB,QAAS,OAAOC,QAASC,GAAO9G,KAAKiG,aAAaa,GAAK,CAACA,EAAG9G,KAAKoD,aAAa0D,IAAM,IAC1HC,QAAQC,MAAM,oBAAoBpD,EAAKT,EAAI,CAACnD,KAAKiH,aAAcL,MAAQnI,EACzE,CAOQ4C,GAAM6F,EAAc/D,EAAO9D,GAAyB,UACxCW,KAAKC,OAAQyG,GAASQ,GADkB,GACT7H,KAAKA,EAAOZ,GAAMuB,KAAK2G,GAAOxD,EAAI1E,GACrF,GAQE0I,EAAyC,GAMtC,SAASC,IACd,OAAAD,EAAOA,EAAK3I,OAAQ8E,GAAMA,EAAE+D,UAChBlI,IAAKmE,GAAMA,EAAE+D,QAC3B,CAeO,SAASC,EAAeC,EAA2BC,GACpDD,GAASE,EAAUF,GAVlB,SAAgBC,EAAkCE,gBACvDC,IACKP,IAAaQ,SAASJ,IAAWL,EAAKU,KAAK,IAAIC,QAAQN,IAC5D,IAAMO,EAAMC,EAAOC,SAASrG,WACF,IAAtB4F,EAASjJ,IAAIwJ,IAAoBP,EAASU,OAAOH,EAAK,cAAclI,KACxEsB,EAAMgH,KAAOX,EACf,CAKEU,CAAOV,EACT,CAMO,IAAMY,EAAiBhK,GAA+CU,EAAiBV,UAAIiK,OAAAC,EAAAC,OAAAC,OAAAC","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["loads","readyByRoot","WeakMap","enroll","el","root","getRootNode","set","get","filter","e","i","a","isConnected","lastIndexOf","getBindingsReady","list","els","Promise","any","map","initializePromise","then","bound","connectedCallbackPromise","length","reject","errors","HTMLElementBase","HTMLElement","WcsState","constructor","super","this","engine","started","failed","initial","claimed","loaded","receiveInitial","resolve","resolveConnected","rejectConnected","catch","resolveInitialize","hasConnectedCallbackPromise","connectedCallback","connected","engines","has","drainBinds","hooks","element","rerun","claim","lenient","parentNode","ShadowRoot","load","loadState","state","start","built","fail","disconnectedCallback","disconnected","delete","setInitialState","raise","reset","receive","createState","mutability","callback","readonlyDepth","proxy","createStateAsync","Proxy","t","k","receiver","v","Reflect","id","getAttribute","find","r","querySelectorAll","x","script","document","Error","text","JSON","parse","textContent","src","async","url","URL","baseURI","href","test","res","fetch","ok","status","json","default","loadSrc","querySelector","blocked","seen","effectiveDirective","startsWith","addEventListener","blob","createObjectURL","Blob","type","encodeURIComponent","setTimeout","message","String","cause","removeEventListener","revokeObjectURL","loadInnerScript","host","hasAttribute","requireFeature","loading","loadFeatures","other","Engine","DirtyStrategy","mount","watchRendered","callHook","report","at","flatMap","n","console","error","localName","name","refs","registries","deref","bootstrapState","partial","registry","setConfig","customElements","installBinder","includes","push","WeakRef","tag","config","tagNames","define","tags","buildBindings","b","j","I","z","q"],"sources":["../../../src/element.ts"],"sourcesContent":["import type { IWritableConfig } from \"./public/types\";\nimport { Engine } from \"./engine\";\nimport { engines, mount } from \"./dom/mount\";\nimport { drainBinds, installBinder } from \"./dom/binder\";\nimport { DirtyStrategy } from \"./strategy/dirty\";\nimport { config, setConfig } from \"./config\";\nimport type { Strategy } from \"./strategy/types\";\nimport { raise, M, text } from \"./messages\";\nimport { hooks, loadFeatures, requireFeature, type Claimed } from \"./hooks\";\n\nlet makeStrategy: () => Strategy = () => new DirtyStrategy();\n\n/** Chooses the invalidation strategy of every engine created from now on. */\nexport function configure(factory: () => Strategy): void {\n makeStrategy = factory;\n}\n\nlet loads = 0;\n\nasync function loadInnerScript(script: HTMLScriptElement): Promise<Record<string, any>> {\n // an import a Content-Security-Policy blocked rejects without saying why: the violation event\n // is the only witness (docs/csp.md §9)\n let blocked = false;\n const seen = (e: SecurityPolicyViolationEvent): void => {\n if (e.effectiveDirective.startsWith(\"script-src\")) blocked = true;\n };\n document.addEventListener(\"securitypolicyviolation\", seen);\n // a server (@wcstack/server) removes createObjectURL: a data: URL, unique so no load is cached\n const blob = typeof URL.createObjectURL === \"function\";\n const url = blob\n ? URL.createObjectURL(new Blob([script.text], { type: \"application/javascript\" }))\n : \"data:text/javascript;charset=utf-8,\" + encodeURIComponent(`${script.text}\\n//${++loads}`);\n try {\n const mod = await import(/* @vite-ignore */ url);\n return (mod.default ?? {}) as Record<string, any>;\n } catch (e) {\n // Firefox fires the violation a task after the rejection (Chromium and WebKit before it)\n await new Promise((r) => setTimeout(r));\n throw new Error(`[@wcstack/state] ${blocked ? text(M.InlineBlocked) : text(M.InlineFailed, [e instanceof Error ? e.message : String(e)])}`, { cause: e });\n } finally {\n document.removeEventListener(\"securitypolicyviolation\", seen);\n if (blob) URL.revokeObjectURL(url);\n }\n}\n\nasync function loadSrc(src: string): Promise<Record<string, any>> {\n const url = new URL(src, document.baseURI).href;\n if (/\\.json(?:[?#]|$)/.test(url)) {\n const res = await fetch(url);\n if (!res.ok) raise(M.LoadFailed, [src, res.status]);\n return (await res.json()) as Record<string, any>;\n }\n const mod = await import(/* @vite-ignore */ url);\n return (mod.default ?? {}) as Record<string, any>;\n}\n\n/**\n * The root `<wcs-state>` elements of each root node (and the one a component mount or a DCC definition\n * has in its shadow root): a new list whenever one connects, without the ones no longer in the page.\n */\nconst readyByRoot = new WeakMap<Node, WcsState[]>();\n\n/**\n * Puts `el` among the `<wcs-state>` elements of `root` (a new list, without the ones that left) — or,\n * taken out of it, takes it off: the list holds nothing of a page that went.\n */\nfunction enroll(el: WcsState, root: Node = el.getRootNode()): void {\n readyByRoot.set(root, [...(readyByRoot.get(root) ?? []), el].filter((e, i, a) => e.isConnected && a.lastIndexOf(e) === i));\n}\n\n/**\n * Resolves when the bindings of `root` are built — by any `<wcs-state>` in it now, whatever its\n * `$connectedCallback` does then, as 3.x — and rejects, with the first failure, only when every one\n * failed before building them. A stray one (a second root, #47; one that fails to load) changes\n * nothing while another binds the root; one taken out of the page (or moved to another root) counts\n * no more (a root replaced: the new one decides). With none in it — none ever, or only ones that left —\n * it resolves at once: there is nothing to wait for (a page without state).\n */\nexport function getBindingsReady(root: Node): Promise<void> {\n const list = readyByRoot.get(root) ?? [];\n const els = list.filter((e) => e.getRootNode() === root);\n return Promise.any(els.map((el) => el.initializePromise.then((): unknown => el.bound || el.connectedCallbackPromise))).then(\n () => {},\n // none, or every one failed: one connected since (the list is a new one) may still bind the root\n // (quoted: `errors` is a name the build shortens, an AggregateError's is not)\n (e: AggregateError) => (els.length ? readyByRoot.get(root) !== list ? getBindingsReady(root) : Promise.reject(e[\"errors\"][0]) : undefined),\n );\n}\n\n/**\n * The base of the package's elements: HTMLElement, or — where there is none (Node without a DOM)\n * — an inert class, so the entries can be imported headless (a tool reading the manifest, a\n * server framework importing at the top level), as 3.x. Making an element stays a browser's.\n */\nexport const HTMLElementBase = (typeof HTMLElement === \"undefined\" ? class {} : HTMLElement) as typeof HTMLElement;\n\n/**\n * `<wcs-state>` — one engine per element, bound to the element's root node.\n * State resolution order: `state` (id of a JSON script) → `src` → `json` → inner\n * `<script type=\"module\">` → wait for `setInitialState()`.\n */\nexport class WcsState extends HTMLElementBase {\n static getBindingsReady = getBindingsReady;\n /** Servers (@wcstack/server) wait on connectedCallbackPromise when this is set. */\n static hasConnectedCallbackPromise = true;\n\n engine: Engine | null = null;\n readonly connectedCallbackPromise: Promise<void>;\n /**\n * Resolves once the state is loaded and bound (before `$connectedCallback`) — and also when\n * initialization fails: the failure is delivered on connectedCallbackPromise.\n */\n readonly initializePromise: Promise<void>;\n private resolveInitialize!: () => void;\n private resolveConnected!: () => void;\n private rejectConnected!: (e: unknown) => void;\n private started = false;\n /** Initialization failed before the page was bound: `setInitialState` refuses (#14). */\n private failed = false;\n private initial: Record<string, any> | null = null;\n /** Taken over by an add-on (a volume, a DCC definition): it never becomes a root. */\n private claimed: Claimed | null = null;\n /** A claimed element's state is loaded: `setInitialState` from now on is the add-on's re-set. */\n private loaded = false;\n /** The root's bindings are built (getBindingsReady resolves, whatever `$connectedCallback` does). */\n bound?: boolean;\n private receiveInitial: ((state: Record<string, any>) => void) | null = null;\n\n constructor() {\n super();\n this.connectedCallbackPromise = new Promise<void>((resolve, reject) => {\n this.resolveConnected = resolve;\n this.rejectConnected = reject;\n });\n this.connectedCallbackPromise.catch(() => {});\n this.initializePromise = new Promise<void>((resolve) => {\n this.resolveInitialize = resolve;\n });\n }\n\n connectedCallback(): void {\n if (this.started) {\n if (this.claimed !== null) {\n this.claimed.connected();\n return;\n }\n enroll(this);\n const engine = this.engine;\n if (engine !== null) {\n // back in the page: it holds its root again (unless another <wcs-state> bound it meanwhile),\n // binds what was handed over while it was out, and the add-ons hear of it (the volumes that\n // connected meanwhile graft) — then $connectedCallback runs again\n const root = engine.root;\n if (root === this.getRootNode() && !engines.has(root)) engines.set(root, engine);\n drainBinds();\n hooks.element?.(engine, \"back\");\n this.rerun(\"$connectedCallback\", M.ConnectedFailed, () => {\n if (this.isConnected) hooks.element?.(engine, \"connected\");\n });\n }\n return;\n }\n this.started = true;\n const root = this.getRootNode();\n const claimed = hooks.claim?.(this, root);\n if (claimed) {\n this.claimed = claimed;\n // the `<wcs-state>` of the shadow root it binds (a component's, a DCC definition's) is that\n // root's, as 3.x: getBindingsReady there waits for it — until its bindings are built, as a\n // root's — and fails with it (a volume never fails)\n if (!claimed.lenient && this.parentNode instanceof ShadowRoot) enroll(this);\n void (claimed.load === undefined ? this.loadState() : claimed.load()).then((state) => {\n this.loaded = true;\n return claimed.start(state, () => this.built());\n }).then(() => {\n this.resolveInitialize();\n this.resolveConnected();\n }, (e) => this.fail(e, claimed.lenient));\n return;\n }\n void this.start(root);\n enroll(this);\n }\n\n disconnectedCallback(): void {\n if (this.claimed !== null) {\n this.claimed.disconnected();\n return;\n }\n const engine = this.engine;\n if (engine === null) return;\n // out of the page, it lets go of its root (it holds it again when it is back): what outlives the\n // page's content — its root node, the document — does not keep its state and the DOM it bound\n // (a root that failed before its mount has none: enroll takes the root it is in now)\n const root = engine.root;\n if (engines.get(root!) === engine) engines.delete(root!);\n enroll(this, root);\n this.rerun(\"$disconnectedCallback\", M.DisconnectedFailed);\n hooks.element?.(engine, \"disconnected\");\n }\n\n /**\n * Supplies the initial state; on an initialized element, replaces the whole state and\n * re-applies every binding to it before returning (not a write: no `$renderedCallback`).\n */\n setInitialState(state: Record<string, any>): void {\n if (this.failed) raise(M.ElementFailed);\n // (until a claimed element's state is loaded, this supplies it like a root's)\n if (this.loaded) {\n this.claimed!.reset(state);\n return;\n }\n if (this.engine !== null) {\n this.engine.reset(state);\n return;\n }\n if (this.receiveInitial !== null) {\n const receive = this.receiveInitial;\n this.receiveInitial = null;\n receive(state);\n } else {\n this.initial = state;\n }\n }\n\n /** Runs `callback` with a state proxy; its writes are applied in the next drain. */\n createState(mutability: \"readonly\" | \"writable\", callback: (state: Record<string, any>) => void): void {\n const engine = this.engine;\n if (engine === null) raise(M.NotInitialized);\n if (mutability === \"readonly\") engine.readonlyDepth++;\n try {\n callback(engine.proxy);\n } finally {\n if (mutability === \"readonly\") engine.readonlyDepth--;\n }\n }\n\n /** `createState` whose callback may await; a readonly proxy stays readonly across its awaits. */\n async createStateAsync(mutability: \"readonly\" | \"writable\", callback: (state: Record<string, any>) => Promise<void>): Promise<void> {\n const engine = this.engine;\n if (engine === null) raise(M.NotInitialized);\n await callback(mutability === \"writable\" ? engine.proxy : new Proxy(engine.proxy, {\n // as in createState(\"readonly\"), the writes of $setAll and $resolve (path, indexes, value) refuse;\n // read with this view as the receiver, a method comes as it is and runs on this view\n get(t, k, receiver) {\n const v = Reflect.get(t, k, receiver);\n return k === \"$setAll\" || k === \"$resolve\" ? (...a: unknown[]) => (a.length > 2 && raise(M.Readonly), v(...a)) : v;\n },\n set() {\n raise(M.Readonly);\n },\n }));\n }\n\n private async loadState(): Promise<Record<string, any>> {\n // a parser that inserts the element before its children (a server render) has added them by now\n await 0;\n const id = this.getAttribute(\"state\");\n if (id !== null) {\n // a JSON script of that id (an element of user content with the same id, earlier, is not it)\n const find = (r: Node): HTMLScriptElement | undefined =>\n [...(r as Document).querySelectorAll<HTMLScriptElement>('script[type=\"application/json\"]')].find((x) => x.id === id);\n const script = find(this.getRootNode()) ?? find(document);\n if (script === undefined) return Promise.reject(new Error(`[@wcstack/state] ${text(M.NoScript, [id])}`));\n return Promise.resolve(JSON.parse(script.textContent || \"{}\"));\n }\n const src = this.getAttribute(\"src\");\n if (src !== null) return loadSrc(src);\n const json = this.getAttribute(\"json\");\n if (json !== null) return Promise.resolve(JSON.parse(json));\n const script = this.querySelector('script[type=\"module\"]') as HTMLScriptElement | null;\n if (script !== null) return loadInnerScript(script);\n if (this.initial !== null) return Promise.resolve(this.initial);\n return new Promise((resolve) => {\n this.receiveInitial = resolve;\n });\n }\n\n private async start(root: Node): Promise<void> {\n try {\n // what an add-on serves: a volume, a component mount, a DCC definition, server rendering\n const host = (root as ShadowRoot).host;\n if (this.hasAttribute(\"mount\") || this.hasAttribute(\"bind-component\") || host?.hasAttribute(\"data-wc-definition\")) {\n requireFeature(\"scopes\", \"<wcs-state>\");\n }\n const state = await this.loadState();\n const loading = loadFeatures(state);\n if (loading) await loading;\n // taken out of its root while it loaded (the page's content replaced, or moved to another root):\n // nothing is mounted on the root it left. It starts again where it is now, or when it connects\n // again. A state given by setInitialState() is kept for that; a state= / src= / json= / inline\n // script source is read again (a fetch runs again, an inline module is evaluated again)\n if (this.getRootNode() !== root) {\n this.initial = state;\n this.started = false;\n if (this.isConnected) this.connectedCallback();\n return;\n }\n if (this.hasAttribute(\"enable-ssr\")) requireFeature(\"ssr\", \"enable-ssr\");\n // one state tree per root: another <wcs-state> already bound this root (and still does —\n // whatever its $connectedCallback did then), or a component's took it\n const other = engines.get(root)?.element as WcsState | undefined;\n if (other?.isConnected && (other.bound || other.claimed)) raise(M.SecondRoot);\n const engine = new Engine(state, makeStrategy());\n engine.element = this;\n this.engine = engine;\n hooks.element?.(engine, \"mounting\");\n mount(engine, root as Document | ShadowRoot);\n drainBinds();\n engine.watchRendered();\n this.built();\n await engine.callHook(\"$connectedCallback\");\n if (this.isConnected) hooks.element?.(engine, \"connected\");\n this.resolveConnected();\n } catch (e) {\n // (a root that bound its page and whose $connectedCallback then failed has not: re-set stays open)\n this.failed = !this.bound;\n this.fail(e);\n }\n }\n\n /** The bindings are built (before `$connectedCallback`): getBindingsReady resolves, initializePromise too. */\n private built(): void {\n this.bound = true;\n this.resolveInitialize();\n }\n\n /**\n * Initialization failed: reported once, the element (and where its state comes from) before what\n * was thrown, as 3.5 — `<wcs-state src=\"./state.js\"> failed to initialize.`, or, once its\n * bindings were built, `… $connectedCallback failed.` — and connectedCallbackPromise rejects with\n * it, or resolves for a claim that is `lenient` (a volume).\n */\n private fail(e: unknown, lenient?: boolean): void {\n this.report(this.bound ? M.ConnectedFailed : M.InitFailed, e);\n this.resolveInitialize();\n if (lenient) this.resolveConnected();\n else this.rejectConnected(e);\n }\n\n /** Reports a failure once: the element (and where its state comes from), then what was thrown. */\n private report(id: M, e: unknown): void {\n const at = [\"mount\", \"bind-component\", \"state\", \"src\"].flatMap((n) => (this.hasAttribute(n) ? [n, this.getAttribute(n)] : []));\n console.error(`[@wcstack/state] ${text(id, [this.localName, ...at])}`, e);\n }\n\n /**\n * Runs a lifecycle callback of a root that connected before (on reconnect, on disconnect) at once: a\n * failure — thrown or rejected — is reported as a first connection's is, never thrown out of the\n * element's callback.\n */\n private rerun(name: string, id: M, then?: () => void): void {\n void (async () => this.engine!.callHook(name))().then(then, (e) => this.report(id, e));\n }\n}\n\n/**\n * The registries `<wcs-state>` was defined in: an add-on installed later defines its tags there\n * too. Weak: a server creates a registry per render, and holding them would keep every render's\n * registry (and every constructor defined in it) alive.\n */\nlet refs: WeakRef<CustomElementRegistry>[] = [];\n\n/**\n * The registries still alive (dead references are dropped). A registry deref() returned stays\n * alive until the end of this job, so the second deref() of each kept reference finds it.\n */\nexport function registries(): CustomElementRegistry[] {\n refs = refs.filter((r) => r.deref());\n return refs.map((r) => r.deref()!);\n}\n\n/**\n * Registers `<wcs-state>` (and the installed add-ons' tags) in `registry` — a scoped registry\n * does not inherit the global one, so a tree using one needs its own definitions.\n */\nexport function define(registry: CustomElementRegistry = customElements): void {\n installBinder();\n if (!registries().includes(registry)) refs.push(new WeakRef(registry));\n const tag = config.tagNames.state;\n if (registry.get(tag) === undefined) registry.define(tag, class extends WcsState {});\n hooks.tags?.(registry);\n}\n\n/** Applies `config` and registers `<wcs-state>`. The core only: install the add-ons first. */\nexport function bootstrapState(partial?: IWritableConfig, registry?: CustomElementRegistry): void {\n if (partial) setConfig(partial);\n define(registry);\n}\n\n/**\n * Waits for the bindings under `root` (3.x built them here; the new engine builds them when the\n * root's `<wcs-state>` loads its state, so this only waits — the same as getBindingsReady).\n */\nexport const buildBindings = (root: Document | ShadowRoot): Promise<void> => getBindingsReady(root);\n"],"mappings":"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","ignoreList":[]}
|